A:http://codeforces.com/contest/1399/problem/A
解析:
不多说了,直接sort,判是否存在相邻差>1
#include<iostream> #include<cstring> #include<algorithm> #include<stack> using namespace std; typedef long long ll; const int maxn=60; int l[maxn],r[maxn]; char ch[3*maxn]; int a[maxn]; int pos[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; if(n==1) { cout<<"YES"<<endl;continue; } sort(a+1,a+1+n); int ok=0; for(int i=2;i<=n;i++) if(abs(a[i]-a[i-1])>1) { ok=1;break; } if(ok) cout<<"NO"<<endl; else cout<<"YES"<<endl; } }
B:http://codeforces.com/contest/1399/problem/B
题意:
长度为n的a[]和b[]
三种操作:
1. ai--
2. bi--
3. ai和bi同时减1
分别把a[]和b[]变成全相等数组,问最少需要的操作数。a[]不一定要和b[]相等。
解析:
因为只存在自减操作,所以元素并不会增大。所以最少需要的操作,一定是a[]和b[]变成对应的最小值。
所以先找到各自的最小值。
遍历a[]和b[],对于每一个ai,bi,算出俩差值,先同时减,然后较大的再自减就可以了。
#include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<map> using namespace std; typedef long long ll; const int maxn=60; const int mod=1e9+7; int l[maxn],r[maxn]; char ch[3*maxn]; ll a[maxn]; ll b[maxn]; ll c[maxn],d[maxn]; int pos[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; map<ll,ll>m1; map<ll,ll>m2; int tot1=0,tot2=0; ll mina=mod,minb=mod; for(int i=1;i<=n;i++) { cin>>a[i]; mina=min(a[i],mina); } for(int i=1;i<=n;i++) { cin>>b[i]; minb=min(b[i],minb); } ll cnt=0; for(int i=1;i<=n;i++) { int m1=a[i]-mina; int m2=b[i]-minb; if(m1>m2) { cnt+=m2; cnt+=m1-m2; } if(m1==m2) cnt+=m1; if(m1<m2) { cnt+=m1; cnt+=m2-m1; } } cout<<cnt<<endl; } }
C:http://codeforces.com/contest/1399/problem/C
题意:
有n个人想参加划船比赛。第i个参与者的权重是wi。
只有两人组成的团队可以参加比赛。
如果有k个团队(a1,b1),(a2,b2),…,(ak,bk),其中ai是第i个团队的第一个参与者的权重,bi是第二个团队的权重第i个团队的参与者,则必须满足条件a1 + b1 = a2 + b2 =⋯= ak + bk = s,其中s是每个团队的总权重。问有多少个团队可以参赛。
解析:
n==50,直接三重for暴力遍历每一个和值即可。
先统计不同的两两和,然后对它们进行暴力枚举,看每一个值能组成多少团队,取最大即可。
#include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<map> using namespace std; typedef long long ll; const int maxn=60; const int mod=1e9+7; int l[maxn],r[maxn]; char ch[3*maxn]; int a[maxn]; int b[8*maxn]; int vis[maxn]; ll c[maxn],d[maxn]; int pos[maxn]; int main() { int t; cin>>t; while(t--) { memset(vis,0,sizeof(vis)); int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } int tot=0; map<int,int>m1; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { int md=a[i]+a[j]; if(!m1[md]) b[tot++]=md; m1[md]=1; } } int maxx=0; for(int i=0;i<tot;i++) { memset(vis,0,sizeof(vis)); int cnt=0; int md=b[i]; for(int j=1;j<=n;j++) { for(int c=j+1;c<=n;c++) { int md2=a[j]+a[c]; if(!vis[j]&&!vis[c]&&md2==md) { cnt++; vis[j]=1; vis[c]=1; } } } maxx=max(maxx,cnt); } cout<<maxx<<endl; } }
D:http://codeforces.com/contest/1399/problem/D
题意:
给定一个字符串由0/1组成,问最少有几个字符串是01间隔的(010101……或者101010……)。输出最少的个数和每个字符在第几个子字符串。
解析:
是存在贪心思想的。
因为要想个数更少,肯定对于遍历到的每个0,要接到它之前已经存在的0101...上,而不是另开一个新子串,只有之前没得接的时候,才需要另开新子串。
用到两个队列,一个是stack st[2],用来存以0/1结尾的符合条件的子序列编号。
vector用来存每个字符属于第几个子串。
接下来看注释吧:
#include<iostream> #include<stack> #include<vector> using namespace std; typedef long long ll; int main() { int t; cin>>t; while(t--) { int n; cin>>n; string s; cin>>s; stack<int>st[2]; vector<int>vv; int len=s.length(); int all=1; for(int i=0;i<len;i++) { int now=s[i]-'0'; if(st[now^1].empty()) //now对应的字符,如果没得接,就新开一个子串 { st[now^1].push(all++); } int top=st[now^1].top(); //找到s[i]可以接的子串编号 vv.push_back(top); //存入s[i]所属子串编号 st[now^1].pop(); // 现在的第top子串,已经接上了s[i],那么它的末尾就变了, 0->1/1->0,所以要把top传过去 st[now].push(top); } all--; cout<<all<<endl; for(int i=0;i<vv.size();i++) cout<<vv[i]<<" "; cout<<endl; } }