Codeforces Round 898 (Div. 4)A~H
A. Short Sort 题意:输出不一样的字符的个数
思路:模拟即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { string s; string t = "abc" ; cin>>s; int cnt = 0 ; for (int i = 0 ;i < 3 ; i++) { if (s[i] != t[i])cnt++; } if (cnt>2 )cout<<"NO\n" ; else cout<<"YES\n" ; } return 0 ; }
B. Good Kid 题意:可以选一个数+1,然后把所有数乘起来,问如何操作使得值最大。
思路:排序,把最大的+1即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;ll a[N]; int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { int n; cin>>n; for (int i = 1 ;i <= n; i++) cin>>a[i]; sort (a+1 ,a+1 +n); a[1 ] += 1 ; ll ans = 1 ; for (int i = 1 ;i <= n; i++) ans *= a[i]; cout<<ans<<"\n" ; } return 0 ; }
C. Target Practice 题意:每一圈有一个权值,问总分数。
思路:模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 20 ;char a[N][N];int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { for (int i = 1 ;i <= 10 ; i++) for (int j = 1 ;j <= 10 ; j++) cin>>a[i][j]; ll ans = 0 ; for (int j = 1 ;j <= 10 ; j++) { if (a[1 ][j]=='X' )ans += 1 ; if (a[10 ][j]=='X' )ans += 1 ;} for (int j = 2 ;j <= 9 ; j++) { if (a[2 ][j]=='X' )ans += 2 ; if (a[9 ][j]=='X' )ans += 2 ;} for (int j = 3 ;j <= 8 ; j++) { if (a[3 ][j]=='X' )ans += 3 ; if (a[8 ][j]=='X' )ans += 3 ;} for (int j = 4 ;j <= 7 ; j++) { if (a[4 ][j]=='X' )ans += 4 ; if (a[7 ][j]=='X' )ans += 4 ;} for (int j = 5 ;j <= 6 ; j++) { if (a[5 ][j]=='X' )ans += 5 ; if (a[6 ][j]=='X' )ans += 5 ;} for (int i = 2 ;i <= 9 ; i++) { if (a[i][1 ]=='X' )ans += 1 ; if (a[i][10 ]=='X' )ans += 1 ;} for (int i = 3 ;i <= 8 ; i++) { if (a[i][2 ]=='X' )ans += 2 ; if (a[i][9 ]=='X' )ans += 2 ;} for (int i = 4 ;i <= 7 ; i++) { if (a[i][3 ]=='X' )ans += 3 ; if (a[i][8 ]=='X' )ans += 3 ;} for (int i = 5 ;i <= 6 ; i++) { if (a[i][4 ]=='X' )ans += 4 ; if (a[i][7 ]=='X' )ans += 4 ;} cout<<ans<<"\n" ; } return 0 ; }
D. 1D Eraser 题意:每次可以把连续的 个细胞变成白色,问最少变多少次可以把所有的变白。
思路:暴力模拟即可。发现是黑的把它往后 个变白。注意边界。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { int n,k; cin>>n>>k; string s; cin>>s; s = "?" +s; int cnt = 0 ; for (int i = 1 ;i <= n; i++) { if (s[i]=='B' ) { for (int j = i;j <= min (n,i+k-1 ); j++) s[j] = 'W' ; i = i+k-1 ; cnt++; } } cout<<cnt<<"\n" ; } return 0 ; }
E. Building an Aquarium 题意:给你 个点放的砖块的个数,往里面加水,问墙壁最大建多高,能满足装的水不超过 。
思路:二分答案。用砖块个数-墙壁高度,负数部分是可以装水部分,按照这个来check即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;ll a[N],l_max[N],r_max[N],b[N]; ll n,x; bool judge (ll h) { ll ans = 0 ; for (int i = 1 ;i <= n; i++) b[i] = a[i]; for (int i = 1 ;i <= n; i++) { b[i] -= h; if (b[i]<0 ) ans += abs (b[i]); } return ans<=x; } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { cin>>n>>x; for (int i = 1 ;i <= n; i++) cin>>a[i]; ll l = 1 ,r = 1e11 ; while (l<=r) { ll mid = (l+r)>>1 ; if (judge (mid))l = mid+1 ; else r = mid-1 ; } cout<<l-1 <<"\n" ; } return 0 ; }
F. Money Trees 题意:当 能被 整除,我们可以选择一段连续的子集合 ,并获得对应的 的值的和。问,当我们 的和不能超过 时候的能取的最大的子集长度是多少?
思路:先预处理出符合整除条件的区间,但是这些区间不一定满足和小于等于 ,那么对于这些区间,我们枚举左端点二分右端点,答案对长度取 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;ll a[N],h[N],pre[N]; int n,k;bool judge (int l,int r) { return pre[r]-pre[l-1 ]<=k; } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { cin>>n>>k; vector<pair<int ,int >>res; for (int i = 1 ;i <= n; i++) cin>>a[i],pre[i] = 0 ; for (int i = 1 ;i <= n; i++) cin>>h[i]; for (int i = 1 ;i <= n; i++) pre[i] = pre[i-1 ]+a[i]; int l = 1 ,r = 1 ; while (r<=n-1 ) { if (h[r]%h[r+1 ]) res.push_back ({l,r}),l = r+1 ; r++; } if (l!=n) res.push_back ({l,n}); for (int i = 1 ;i <= n; i++) res.push_back ({i,i}); int ans = 0 ; for (auto [ll,rr]:res) { int l = ll,r = rr; if (pre[r]-pre[l-1 ]<=k) ans = max (ans,r-l+1 ); else { for (int i = l;i <= r; i++) { int l_r = i,r_r = r; while (l_r<=r_r) { int mid = (l_r+r_r)>>1 ; if (judge (i,mid))l_r = mid+1 ; else r_r = mid-1 ; } ans = max (ans,l_r-1 -i+1 ); } } } cout<<ans<<"\n" ; } return 0 ; }
G. ABBC or BACB 题意:你可以进行一下操作:
选择一个子串 变成 并获得一个硬币
选择一个子串 变成 并获得一个硬币
问最多可以获得多少硬币?
思路:考虑对于一个子串,我们如何变更优?
对于 我们变成 。对于 我们变成 。能变的次数是 左边或者右边 的个数。
那么考虑对于一个串 ,能有贡献的段是 的个数,那么我们处理出连续的 的个数,然后排序,取前 个是答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;int le[N],ri[N];bool cmp (int x,int y) { return x>y; } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { string s; cin>>s; int sz = s.size (); s = "?" +s; int cnt = 0 ; vector<int >v; int b = 0 ; ll ans = 0 ; for (int i = 1 ;i <= sz; i++) if (s[i] == 'A' ) cnt++; else v.push_back (cnt),cnt = 0 ,b++; v.push_back (cnt); sort (v.begin (),v.end (),cmp); if (!b) cout<<0 <<"\n" ; else {for (int i = 0 ;i < b;i++) ans += v[i]; cout<<ans<<"\n" ;} } return 0 ; }
H. Mad City 题意:有两个人 和 ,告诉你起始位置, 可以预知 的位移,问 是否一定可以逃跑。
思路:考虑什么时候可以逃跑?当 在环里面的时候可以逃跑。那么如果当前不在环里面,就考虑 到环上的点和 到该点的距离,如果 那么可以逃跑。那么接下来如果我知道哪些点是环上的点,在做一个 是不是就解决了。那么现在问题变成了:如何确定哪些点是环上的点呢?是 排序。
关于如何用topo排序判环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int N = 2e5 + 10 ;int n,a,b,d[N];bool vis[N];ll dist1[N],dist2[N]; vector<int > e[N]; bool vis2[N];int tot,l[N];void toposort () { queue<int > q; tot = 0 ; for (int i = 1 ;i <= n; i++) vis2[i] = 0 ; for (int i = 1 ; i <= n; i++) if (d[i] == 1 ) q.push (i),vis2[i] = true ; while (!q.empty ()) { int u = q.front (); q.pop (); for (auto v : e[u]) if (--d[v] <= 1 && !vis2[v]) q.push (v),vis2[v] = true ; } } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ), cout.tie (nullptr ); int t; cin>>t; while (t--) { cin>>n>>a>>b; for (int i = 1 ;i <= n; i++) e[i].clear (),dist1[i] = 0 ,dist2[i] = 0 ,d[i] = 0 ; for (int i = 1 ; i <= n; i++) { int x , y; cin>>x>>y; e[x].push_back (y); e[y].push_back (x); d[y]++; d[x]++; } toposort (); queue<pair<int ,ll>>q; q.push ({a,0 }); dist1[a] = 0 ; memset (vis,false ,sizeof (vis)); vis[a] = true ; while (!q.empty ()) { auto i = q.front (); q.pop (); int u = i.first,dis = i.second; for (auto v : e[u]) { if (!vis[v]) { vis[v] = true ; dist1[v] = dis + 1 ; q.push ({v,dist1[v]}); } } } q.push ({b,0 }); dist2[b] = 0 ; memset (vis,false ,sizeof (vis)); vis[b] = true ; while (!q.empty ()) { auto i = q.front (); q.pop (); int u = i.first,dis = i.second; for (auto v : e[u]) { if (!vis[v]) { vis[v] = true ; dist2[v] = dis + 1 ; q.push ({v,dist2[v]}); } } } bool ok = false ; for (int i = 1 ;i <= n;i++) { if (d[i]>1 &&dist1[i]>dist2[i])ok = true ; } if (ok)cout<<"YES\n" ; else cout<<"NO\n" ; } return 0 ; }