Educational Codeforces Round 53 (Rated for Div. 2)
A. Diverse Substring(前缀和)
题意:给一个字符串,找出一个子串满足该子串中每个字母出现的次数不超过子串的长度/2,字符串的长度n<1000.
题解:n方枚举子串的起点和终点,对于每个字母建一个前缀和就能知道在任意一个字串中每个字母出现的个数了。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[1010]; int n; int num[30][1010]; int main(){ scanf("%d", &n); scanf("%s", s+1); for(int i = 1; i<=n; i++){ for(int k = 0; k<27; k++){ num[k][i] = num[k][i-1]; } num[s[i]-'a'][i] = num[s[i]-'a'][i-1]+1; } int l = -1, r = -1; for(int i = 1; i<=n; i++){ for(int j = 1; j<=i; j++){ bool flag = true; for(int k = 0; k<28; k++){ if(num[k][i]-num[k][j-1]>(i-j+1)/2){ flag = false; break; } } if(flag == true){ l = j; r = i; } } } if(l!=-1 && r!=-1){ cout<<"YES"<<endl; for(int i = l; i<=r; i++){ cout<<s[i]; } cout<<endl; } else{ cout<<"NO"<<endl; } return 0; }
B. Vasya and Books(模拟+标记)
题意:给一个数组a和数组b,每次把在a数组中元素值等于bi的值的那个元素的下标及其前面的元素都去除,问每次去除多少个元素。
题解:记录一下bi在a中出现的位置,以及当前位置即可。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n, a[200010], b[200010]; int pos[200010]; int main(){ scanf("%d", &n); for(int i = 1; i<=n; i++){ scanf("%d", &a[i]); pos[a[i]] = i; } for(int i = 1; i<=n; i++){ scanf("%d", &b[i]); } int sum = 0, now = 0; for(int i = 1; i<=n; i++){ if(i!=1) cout<<" "; if(pos[b[i]]<now){ cout<<"0"; continue; } int ans; ans = pos[b[i]]-now; now = pos[b[i]]; cout<<ans; } cout<<endl; return 0; }
C. Vasya and Robot
题意:给一系列DURL操作,从(0,0)走到(X,Y),可以任意修改该操作,但是代价是最左修改的位置到最右修改的位置的距离。求最小的代价使得满足条件。
题解:二分该距离,该距离内的操作全部清空,然后看能否填成和剩下值加起来满足条件的。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int n; char s[200010]; int X, Y; int Abs(int i){ return i>0?i:-i; } bool check(int k){ int xsum = 0, ysum = 0; for(int i = k+1; i<=n; i++){ if(s[i] == 'R') xsum++; if(s[i] == 'L') xsum--; if(s[i] == 'U') ysum++; if(s[i] == 'D') ysum--; } bool flag = false; int dx = Abs(xsum-X); int dy = Abs(ysum-Y); if(dx+dy<=k && (k-(dx+dy))%2 == 0){ return true; } int l = 1, r = k; while(r<n){ if(s[l] == 'R') xsum++; if(s[l] == 'L') xsum--; if(s[l] == 'U') ysum++; if(s[l] == 'D') ysum--; if(s[r+1] == 'R') xsum--; if(s[r+1] == 'L') xsum++; if(s[r+1] == 'U') ysum--; if(s[r+1] == 'D') ysum++; l++; r++; dx = Abs(xsum-X); dy = Abs(ysum-Y); if(dx+dy<=k && (k-(dx+dy))%2 == 0){ return true; } } return false; } int main(){ scanf("%d", &n); scanf("%s", s+1); scanf("%d %d", &X, &Y); int l = 0, r = n; int ans = -1; while(l<=r){ int mid = (l+r)>>1; if(check(mid)){ r = mid-1; ans = mid; } else{ l = mid+1; } } printf("%d\n", ans); return 0; }
D. Berland Fair
题意:给一个初始值T,每一次循环遇到比它小的ai就减去它,直到不能减为止,问一共减了多少次。
题解:每一次一定是减到某一个值不能减为止,在那之前可以一次性计算出一共减了多少轮。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; long long n, T; long long a[200010]; int main(){ scanf("%I64d %I64d", &n, &T); long long mi = (1<<20); for(int i = 1; i<=n; i++){ scanf("%I64d", &a[i]); mi = min(mi, a[i]); } long long ans = 0; while(T>=mi){ long long tmp = 0; long long sum = 0; for(int i = 1; i<=n; i++){ if(T>=a[i]){ T-=a[i]; sum++; tmp+=a[i]; } } ans+=sum+T/tmp*sum; T%=tmp; } printf("%I64d\n", ans); return 0; }