Codeforces Round #550 题解
A题
排序后看看相邻位置
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=3e5+10; const int mod=1e9+7; int main(){ ios::sync_with_stdio(false); int n; int i; cin>>n; for(i=1;i<=n;i++){ string s; cin>>s; int flag=0; sort(s.begin(),s.end()); for(int j=1;j<s.size();j++){ if(s[j]-'a'!=s[j-1]-'a'+1){ cout<<"No"<<endl; flag=1; break; } } if(!flag){ cout<<"Yes"<<endl; } } return 0; }
B题
贪心想法,分奇偶存后,排序模拟两种情况去max
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=3e5+10; const int mod=1e9+7; int a[N]; vector<int> num1,num2; bool cmp(int a,int b){ return a>b; } int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; ll sum1=0,sum2=0; for(i=1;i<=n;i++){ cin>>a[i]; if(a[i]%2){ num1.push_back(a[i]); sum1+=a[i]; } else{ num2.push_back(a[i]); sum2+=a[i]; } } sort(num1.begin(),num1.end(),cmp); sort(num2.begin(),num2.end(),cmp); if(num1.size()==0){ cout<<sum2-num2[0]<<endl; return 0; } if(num2.size()==0){ cout<<sum1-num1[0]<<endl; return 0; } ll res1=0; ll res2=0; int j; for(i=0,j=0;i<(int)num1.size()&&j<(int)num2.size();i++,j++){ res1+=num1[i]+num2[j]; } if(i!=int(num1.size())){ res1+=num1[i]; } for(i=0,j=0;i<(int)num1.size()&&j<(int)num2.size();i++,j++){ res2+=num1[i]+num2[j]; } if(i!=int(num2.size())){ res2+=num2[i]; } cout<<sum1+sum2-max(res1,res2)<<endl; return 0; }
C题
如果出现三个相同数字以上是非法
先按大小排序,那么相邻两个相同就要放到不同集合,之后一个正序输出一个倒序输出
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=3e5+10; const int mod=1e9+7; int a[N]; vector<int> num1,num2; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } sort(a+1,a+1+n); int flag=0; for(i=3;i<=n;i++){ if(a[i]==a[i-2]){ cout<<"NO"<<endl; return 0; } } cout<<"YES"<<endl; num1.push_back(a[1]); for(i=2;i<=n;i++){ if(a[i]==a[i-1]) num2.push_back(a[i]); else{ num1.push_back(a[i]); } } cout<<num1.size()<<endl; for(auto x:num1){ cout<<x<<" "; } cout<<endl; cout<<num2.size()<<endl; for(int j=(int)num2.size()-1;j>=0;j--){ cout<<num2[j]<<" "; } cout<<endl; return 0; }
D题
贪心题,只要找到最多的那个把其他都变成他就行了
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=3e5+10; const int mod=1e9+7; int a[N]; int h[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; h[a[i]]++; } int mx=0,flag=0; for(i=0;i<=2e5;i++){ if(h[i]>mx){ mx=h[i]; flag=i; } } for(i=1;i<=n;i++){ if(a[i]==flag){ flag=i; break; } } cout<<n-mx<<endl; for(i=flag-1;i>=1;i--){ if(a[i]!=a[i+1]){ if(a[i]>a[i+1]){ cout<<2<<" "<<i<<" "<<i+1<<endl; } else{ cout<<1<<" "<<i<<" "<<i+1<<endl; } a[i]=a[i+1]; } } for(i=flag+1;i<=n;i++){ if(a[i]!=a[i-1]){ if(a[i]>a[i-1]){ cout<<2<<" "<<i<<" "<<i-1<<endl; } else{ cout<<1<<" "<<i<<" "<<i-1<<endl; } a[i]=a[i-1]; } } return 0; }
E题
观察因为序列保证存在,因此可以看作26进制数,答案就是他们的一般,用数组模拟一下
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=4e5+10; const int mod=1e9+7; int a[N],b[N]; int c[N],d[N]; int main(){ //ios::sync_with_stdio(false); int n; cin>>n; string s,t; cin>>s>>t; s=" "+s; t=" "+t; int i; for(i=1;i<=n;i++){ a[i]=s[i]-97; b[i]=t[i]-97; } int x=0;; for(i=n;i>=0;i--){ c[i]=(a[i]+b[i]+x)%26; x=(a[i]+b[i]+x)/26; } for(i=0;i<=n;i++){ d[i]=(c[i]+26*x)/2; x=(c[i]+26*x)%2; } for(i=1;i<=n;i++){ putchar(d[i]+97); } cout<<endl; return 0; }
F题
首先观察到有奇数环是非法状态,那么这个可以用染色法判断,构造答案的时候发现就是对于一个点,他的所有出点都是一个方向。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=4e5+10; const int mod=1e9+7; int h[N],ne[N],e[N],w[N],idx; int ans[N]; int tmp[N]; int vis[N]; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } void dfs(int u,int now,int fa){ vis[u]=now; int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; if(vis[j]==vis[u]){ cout<<"NO"<<endl; exit(0); } if(vis[j]==-1) dfs(j,3-now,u); if(vis[j]==1&&vis[u]==2){ ans[i]=0,ans[i^1]=1; } else{ ans[i]=1,ans[i^1]=0; } } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int n,m; int i; cin>>n>>m; for(i=1;i<=m;i++){ int a,b; cin>>a>>b; add(a,b,i); add(b,a,i); } memset(vis,-1,sizeof vis); dfs(1,1,-1); cout<<"YES"<<endl; for(i=0;i<2*m;i+=2){ cout<<ans[i]; } cout<<endl; return 0; }
G题
贪心思路,对于两个序列,肯定是递减序列的末尾的数越大越好,递增的末尾越小越好,这样才能使得后面能放的更多
因此当某个数能放在任意一个序列的时候,观察a[i]和a[i+1]的大小,如果大于,则把他放入递减序列,反之则递增序列,这样肯定比反着来至少不劣。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e6+10; const int mod=998244353; const int inf=0x3f3f3f3f; int a[N]; int inc[N],dec1[N],cnt1,cnt2; int ans[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } dec1[0]=inf; inc[0]=-1; for(i=1;i<=n;i++){ if(a[i]<=inc[cnt1]&&a[i]>=dec1[cnt2]){ cout<<"NO"<<endl; return 0; } else if(a[i]>inc[cnt1]&&a[i]<dec1[cnt2]){ if(a[i]>a[i+1]){ dec1[++cnt2]=a[i]; ans[i]=1; } else{ inc[++cnt1]=a[i]; ans[i]=0; } } else if(a[i]>inc[cnt1]){ inc[++cnt1]=a[i]; ans[i]=0; } else{ dec1[++cnt2]=a[i]; ans[i]=1; } } cout<<"YES"<<endl; for(i=1;i<=n;i++){ cout<<ans[i]<<" "; } cout<<endl; }
没有人不辛苦,只有人不喊疼