https://codeforces.com/contest/1907
A题是一个很简单的模拟,就不说了
B题
赛后看有群u们说拿栈模拟
比赛时我想到的是从后到前遍历字符串,维护两个cnt1,cnt2.分别代表B,b出现的次数,出现一次对应cnt++,遍历每一个字符如果对应cnt不为零,这一位就不加入答案,然后cnt–。
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
| #include<bits/stdc++.h> using namespace std; using ll=long long; void solve(){ string s; cin>>s; reverse(s.begin(),s.end()); int cnt1=0; int cnt2=0; int len=s.size(); string ans=""; for(int i=0;i<len;i++){ if(s[i]=='b'){cnt1++;continue;} if(s[i]=='B'){cnt2++;continue;} if(s[i]<='z'&&s[i]>='a'&&cnt1){ cnt1--; continue; } if(s[i]<='Z'&&s[i]>='A'&&cnt2){ cnt2--; continue; } ans+=s[i]; } reverse(ans.begin(),ans.end()); cout<<ans<<'\n'; } int main(){ int _;cin>>_; while(_--)solve(); return 0; }
|
C题
感觉是见过最简单的C了(?
考虑删完所有相邻且不同的字符之后,剩下的一定是一个只含一个字母的子串
所以找到出现次数最多的字母出现次数记为sum
与其不相等的其他字母数量一定为n-sum。
比较sum和n-sum,sum大就输出n-2`*sum,否则输出n%2
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
| #include<bits/stdc++.h> using namespace std; using ll=long long; ll cnt[26]; void solve(){ memset(cnt,0,sizeof cnt); ll n;cin>>n; string s; cin>>s; for(int i=0;i<s.size();i++){ cnt[s[i]-'a']++; } ll mx=*max_element(cnt,cnt+26); n-=mx; if((n+mx)&1){ cout<<((mx-n)<=0?1:(mx-n))<<'\n'; return; } cout<<((mx-n)<=0?0:(mx-n))<<'\n'; } int main(){ int _;cin>>_; while(_--)solve(); return 0; }
|
D题
二分即可,重点在于怎么写check函数
我们可以把每个点扩展到的位置看做一个圆和x轴的左右交点,下一次从这一条线段上任意一点做圆,所以最左端和最右端一定是非递减的
需要注意两点:
1.在扩展的时候要维护两个端点,而不是只维护上一次的一个点
2.二分的时候0是可取答案,如果按我的写法二分应当从-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 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; using ll=long long; const int N=2e5+10; ll l[N]; ll r[N]; ll ans=0; ll n; bool check(ll x){ ll zz=0; ll yy=0; for(int i=1;i<=n;i++){ if(l[i]>(yy+x)||r[i]<(zz-x))return false; else{ zz=max(zz-x,l[i]); yy=min(yy+x,r[i]); } } return 1; } void solve(){ cin>>n; memset(l,0,sizeof l); memset(r,0,sizeof r); for(int i=1;i<=n;i++)cin>>l[i]>>r[i]; ll z=-1; ll y=1e10; while((z+1)!=y){ ll mid=(z+y)>>1; if(check(mid)){ y=mid; } else{ z=mid; } } cout<<y<<'\n'; } int main(){ int _;cin>>_; while(_--)solve(); return 0; }
|
E题
三者不进位,转换为隔板法组合数学,和高中求n个小球分为三份有多少种分法是一样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include<bits/stdc++.h> using namespace std; using ll=long long; void solve(){ string s; cin>>s; ll ans=1; for(auto &c:s){ ans*=(c-'0'+2)*(c-'0'+1)/2; } cout<<ans<<'\n'; } int main(){ int _;cin>>_; while(_--)solve(); }
|
F题
易知颠倒的操作一定发生在头尾
模拟即可
问我为什么做的这么丑,因为我当时很急急急急急急急急急急急急急急急急急急急
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
| #include<bits/stdc++.h> using namespace std; using ll=long long; const int N=4e5+10; int a[N]; ll n,ans=1e9+7; void solve(){ int cnt=1; for(int i=2*n-1;i>=1;i--){ if(a[i]<=a[i+1])cnt++; else cnt=1; if(cnt==n){ans=min(ans,n-i+1);break;} } cnt=1; for(int i=2*n-1;i>=1;i--){ if(a[i]>=a[i+1])cnt++; else cnt=1; if(cnt==n){ans=min(ans,n-i+2);break;} } return ; } void solve2(){ int cnt=1; for(int i=2*n-1;i>=1;i--){ if(a[i]<=a[i+1])cnt++; else cnt=1; if(cnt==n){ans=min(ans,n-i+2);break;} } cnt=1; for(int i=2*n-1;i>=1;i--){ if(a[i]>=a[i+1])cnt++; else cnt=1; if(cnt==n){ans=min(ans,n-i+3);break;} } return ; } int main(){ int _;cin>>_; while(_--){ ans=1e9+7; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; a[i+n]=a[i]; } solve(); if(n==1){ cout<<"0"<<'\n'; continue; } reverse(a+1,a+n+1); for(int i=1;i<=n;i++){ a[i+n]=a[i]; } solve2(); cout<<(ans==1e9+7?-1:ans)<<'\n';; } }
|