A. One-dimensional Japanese Crossword
顺序扫一遍,记录一蛤连续的 'B' 序列就好。
$O(n)$
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 int n; 6 char a[1000]; 7 int ans[1000]; 8 int cnt = 0; 9 int main() 10 { 11 scanf("%d",&n); 12 scanf("%s",&a); 13 for (int i = 0; i < n; i++) 14 { 15 if (a[i] == 'B') ans[cnt]++; 16 else if (ans[cnt] != 0 && a[i] == 'W') cnt++; 17 18 if (ans[cnt] != 0 && i == n-1) cnt++; 19 } 20 printf("%d\n",cnt); 21 for (int i = 0; i < cnt; i++) 22 printf("%d ",ans[i]); 23 printf("\n"); 24 }
B. Passwords
记录每个长度的串的个数,分别讨论一下最优和最差就好了。
$O(n)$
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 using namespace std; 5 6 string str; 7 int len[1000]; 8 int n,k; 9 int c; 10 int total = 0; 11 int main() 12 { 13 scanf("%d %d",&n,&k); 14 for (int i = 0; i < n; i++) 15 { 16 cin>>str; 17 len[str.length()] ++; 18 } 19 cin>>str; 20 c = str.length(); 21 for (int i = 0; i < c; i++) 22 total += len[i]; 23 24 int mini = total + 1; 25 int maxi = total + len[c]; 26 printf("%d %d",mini + (mini - 1)/k*5, maxi + (maxi - 1)/k*5); 27 }
C. Journey
求权值之和不超过T的从1到n的最长路径。由于是拓扑图,BFS+记忆化搜索就可做。记录一下更新的情况还原路径。
$ dp[i][j] = $到第i个点时已经路径长为j时的路径最小花费。
bfs中queue可以改为priority_queue优化
$O((n+m)*m) $
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<queue> 6 #include<stack> 7 using namespace std; 8 9 struct edge{ 10 int to, cost; 11 }; 12 13 struct node{ 14 int p, left, num, _prev; 15 }; 16 int n,m,T; 17 vector<edge> G[5010]; 18 19 int dp[5010][5010]; // 第n个点,已经经过多少个点,所剩余最多的钱 20 int _prev[5010][5010]; //第n个点 已经经过多少个点,前趋 21 22 void solve() 23 { 24 queue<node> que; 25 que.push(node{1,T,1,0}); 26 while(!que.empty()) 27 { 28 node no = que.front(); 29 que.pop(); 30 if (dp[no.p][no.num] >= no.left) continue; 31 else 32 { 33 dp[no.p][no.num] = no.left; 34 _prev[no.p][no.num] = no._prev; 35 36 for (int i = 0; i < G[no.p].size(); i++) 37 { 38 edge e = G[no.p][i]; 39 if (no.left - e.cost < 0 || dp[e.to][no.num + 1] >= no.left - e.cost) { 40 } 41 else 42 { 43 que.push(node{e.to, no.left - e.cost, no.num + 1, no.p}); 44 } 45 } 46 } 47 } 48 int ans = 0; 49 for (int i = n; i >= 1; i--) 50 { 51 if (dp[n][i] != -1) {ans = i; break;} 52 } 53 stack<int> path; 54 path.push(n); 55 int cnt = ans; 56 while(path.top()!= 1 &&cnt >= 0) 57 { 58 path.push(_prev[path.top()][cnt--]); 59 } 60 printf("%d\n",ans); 61 while(!path.empty()) 62 { 63 printf("%d ",path.top()); 64 path.pop(); 65 } 66 printf("\n"); 67 68 } 69 int main() 70 { 71 scanf("%d %d %d",&n,&m,&T); 72 for (int i = 0; i < m; i++) 73 { 74 edge e; 75 int from; 76 scanf("%d %d %d",&from,&e.to,&e.cost); 77 G[from].push_back(e); 78 } 79 80 memset(dp,-1,sizeof dp); 81 solve(); 82 }
D. Maxim and Array
贪心。
使所有元素的乘积最小,首先需要尽可能使其为负数(注意多0的情况)。
利用优先队列维护一下当前所有元素的最小值就好了。
/*
公式推导留坑。
*/
$ O((n+k)logn) $
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<queue> #include<utility> using namespace std; typedef long long ll; typedef pair<ll,ll> P; ll a[200000]; ll n,k,x; ll _abs(ll x) { if (x < 0) return -x; return x; } int sign = 1; int main() { priority_queue<P, vector<P>, greater<P> > que; scanf("%I64d %I64d %I64d",&n,&k,&x); for (int i = 0; i < n; i++) { scanf("%I64d",&a[i]); if (a[i] < 0) { sign = -sign; } que.push(P(_abs(a[i]),i)); } if (n > 0) while( k > 0) { ll pos = que.top().second; ll val = que.top().first; que.pop(); ll times = 0; if (sign == 1) { times = val/x + 1; times = min(times,k); if (a[pos] > 0) a[pos] -= times*x; else if (a[pos] == 0) a[pos] -= times*x; else a[pos] += times*x; sign = -sign; k -= times; val = _abs(a[pos]); que.push(P(val,pos)); continue; } ll aim = que.top().first; times = (aim - val)/x + 1; times = min(times,k); k -= times; if (a[pos] >= 0) a[pos] += times * x; else a[pos] -= times * x; val = _abs(a[pos]); que.push(P(val,pos)); } else a[0] -= k*x; for (int i = 0; i < n; i++) printf("%I64d ",a[i]); printf("\n"); }
E. Road to Home
留坑