Codeforces Global Round 10(A->D(環問題))
A:http://codeforces.com/contest/1392/problem/A
題意:
相鄰的不同數可以相加合成一個數,問最後最少會剩下幾個數
解析:
隨便寫一下,就會發現,只要陣列中只要存在不同數,最後就一定能合成一個數。
所以,全相等,輸出n,否則1
#include<bits/stdc++.h> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const intmaxn=2e5+20; //const ll inf=0x3f3f3f3f3f3f3f3f; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; int ok=0; for(int i=1;i<=n;i++) cin>>a[i]; if(n==1) { cout<<"1"<<endl;continue; } for(int i=2;i<=n;i++) { if(a[i]!=a[i-1]) { ok=1;break; } } if(ok) cout<<"1"<<endl; else cout<<n<<endl; } }
B:http://codeforces.com/contest/1392/problem/B
題意:
每次操作讓當前陣列的最大值去減陣列的每一個數,求第k次操作的陣列
解析:
列了一下,發現,k=1,變一次,k=2,變兩次,k=3,變三次
對於k>1,奇數變三次,偶數變兩次
模擬一下即可。
關於最大值的選擇,不少人賽後被hack掉,所以建議最大值直接設為a[1]妥當。
#include<bits/stdc++.h> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e5+20; //const ll inf=0x3f3f3f3f3f3f3f3f; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; ll k; cin>>n>>k; ll maxx; cin>>a[1]; maxx=a[1]; for(int i=2;i<=n;i++) cin>>a[i],maxx=max(a[i],maxx); if(k==1) { for(int i=1;i<=n;i++) { cout<<maxx-a[i]<<' '; } cout<<endl;continue; } ll maxx2=maxx-a[1]; a[1]=maxx-a[1]; for(int i=2;i<=n;i++) { a[i]=maxx-a[i]; maxx2=max(maxx2,a[i]); } ll maxx3=maxx2-a[1]; a[1]=maxx2-a[1]; for(int i=2;i<=n;i++) { a[i]=maxx2-a[i]; maxx3=max(maxx3,a[i]); } if(k%2==0) { for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;continue; } ll maxx4=maxx3-a[1]; a[1]=maxx3-a[1]; for(int i=2;i<=n;i++) { a[i]=maxx3-a[i]; maxx3=max(maxx3,a[i]); } for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl; } }
C:http://codeforces.com/contest/1392/problem/C
題意:
給出序列,操作:對不遞減的區間裡的每一個數都加1,將整個序列變成非遞減序列所需要的最少運算元。
解析:
本來分析複雜了,涉及到區間問題。但是把序列倒著遍歷,思路就很清晰了。
ai<ai-1,把ai增加到和ai-1相同。
以後再遇到這種情況,ai後集體跟著加1即可。
#include<bits/stdc++.h> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e5+20; //const ll inf=0x3f3f3f3f3f3f3f3f; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; ll ans=0; for(int i=n;i>1;i--) { if(a[i]<a[i-1]) ans+=(a[i-1]-a[i]); } cout<<ans<<endl; } }
D:http://codeforces.com/contest/1392/problem/D
題意:
n個人圍成一圈。字串表示每個人攻擊的是左邊的人還是右邊的人。
合法情況:
如果一個人被攻擊一次,那麼他要反擊那個人
如果一個人被攻擊0或兩次,他可以對左右任選一個攻擊。
將遊戲變成合法,最少需要糾正幾個人?
解析:
先把環變成鏈
1:全L或全R的情況,
RRR->RRL,RRRR->RRLL,RRRRR->RRLRL , RRRRRR->RRLRRL
有結論,此時結果為:n/3+(n%3>0)
2:L和R均有
藉助1的結論,固定到第一個a[k]!=a[0],往後記錄連續和a[k]相等的,cnt++
a[i]!=a[k],記錄總數sum+=cnt/3,cnt重置,k改變
注意對於cnt<3,是不需要改的,這部分肯定是符合條件的。
#include<bits/stdc++.h> #include<map> #include<iostream> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e5+20; char s[3*maxn]; //const ll inf=0x3f3f3f3f3f3f3f3f; ll a[maxn]; int main() { int t; cin>>t; while(t--) { // string s; int n; cin>>n; scanf("%s",s); for(int i=0;i<n;i++) s[i+n]=s[i]; int k=-1; for(int i=1;i<n;i++) { if(s[i]!=s[0]) { k=i; break; } } if(k==-1) { cout<<n/3+(n%3>0)<<endl; continue; } int id=k; ll sum=0; int cnt=0; for(int i=k;i<n+k;i++) { if(s[i]==s[id]) cnt++; else { sum+=cnt/3; cnt=1; id=i; } } sum+=cnt/3; cout<<sum<<endl; } }