A. Fair Game
题目链接:http://codeforces.com/contest/864/problem/A
题意:给你n张牌,n为偶数,一人选一个数字把对应的牌全部拿走,看是否能一人拿一次把牌拿完且两个人拿的数量一样多。
思路:判断是否有两种牌,并且这两种牌的数目相同。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<cmath> using namespace std; #define maxn 100005 typedef long long ll; const int INF=1e9+7; int a[maxn]; int b[maxn]; char s[maxn]; char t[maxn]; map<int,int> vis; queue<int> que; int v[maxn]; int main() { int n,x,y,z; int sum=0; cin>>n; while(n--) { cin>>x; if(!vis[x]) { sum++; vis[x]++; if(sum==1) y=x; else if(sum==2) z=x; } v[x]++; } if(sum!=2||n%2==1||v[y]!=v[z]) { printf("NO\n"); } else { printf("YES\n"); printf("%d %d\n",y,z); } return 0; }
B. Polycarp and Letters
题目链接:http://codeforces.com/contest/864/problem/B
题意:给你一个串,找出所有只有小写字母的字串,并且找每个字串中出现的不同的字母最多有多少个。
思路:对母船扫描一遍边扫描边判断。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; string s; int n; int vis[26]; int main() { cin>>n; cin>>s; int sum=0; int maxx=0; for(int i=0;i<n;i++) { if(s[i]>='A'&&s[i]<='Z') { maxx=max(maxx,sum); sum=0; memset(vis,0,sizeof(vis)); } else { if(vis[s[i]-'a']==0) { vis[s[i]-'a']=1; sum++; } } } maxx=max(sum,maxx); printf("%d\n",maxx); return 0; }
C. Bus
题目链接:http://codeforces.com/contest/864/problem/C
题意:一辆车在0-a之间行驶,车的邮箱容量为b,f是加油站的位置,然后行驶k次,往返算两次,问汽车能否行驶k次,如果能则输出最少的加油次数,否则输出-1.
思路:我们以加油站为起点,此时油箱内的油为b-f如果b<f,则输出-1,否则看剩下的油能否走完k次,如果k大于1的话,我们开一个标记F,如果F==1则汽车经过a回到加油站,此时防线方向F改变为0,及接下来汽车经过起点0,再到加油站方向F变为1,然后判断这样的过程能否实现,当K==1时,如果F==1,则看邮箱内的油能否走到a不能就加油次数+1,如果加了油还不能走到就输出-1,如果F==0,跟前面情况一样。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int main() { int a,b,f,k; scanf("%d%d%d%d",&a,&b,&f,&k); if(b<f) { printf("-1\n"); return 0; } else { int v=b-f; //邮箱剩余的油 int flag=1; int F=1; int sum=0; while(k>1) { if(F) { if((2*(a-f))>b) 如果加了油都不能绕圈,就说明不能走k次,退出循环 flag=0; else { F=0; if((2*(a-f))>v) { sum++; v=b-2*(a-f); } else v=v-2*(a-f); } } else { if((2*f)>b) flag=0; else { F=1; if((2*f)>v) { sum++; v=b-2*f; } else v=v-2*f; } } if(!flag) break; else k--; } if(!flag) { printf("-1\n"); } else { if(F) { if(a-f>b) flag=0; else if((a-f)>v) sum++; } else { if(f>b) flag=0; else if(f>v) sum++; } if(!flag) printf("-1\n"); else printf("%d\n",sum); } } return 0; }
D. Make a Permutation!
题目链接:http://codeforces.com/contest/864/problem/D
题意:给你一个n,然后有n个数,你要用最少的变换次数,使这n个数中1-n各出现一次,并且是数列的字典序最小。
思路:数列从头到尾扫一遍,标记每个数的出现次数,出现0次的数的个数就是变换次数。紧接着从小到大入队列,然后去扫原来的数列,如果一个数的出现次数大于1,并且他比队头的元素大,则他的次数减一并将数列该位置的数变成队头的元素,然后队头的元素出队,如果他比队头的元素小,看他是否被标记过,如果标记过,就说明前面已经出现过一次,直接将他替换掉,否则就不替换,将他标记一下。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define maxn 200005 int num[maxn]; int vis[maxn]; int cnt[maxn]; int main() { int n; scanf("%d",&n); memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); queue<int> que; for(int i=0;i<n;i++) { scanf("%d",&num[i]); vis[num[i]]++; } int sum=0; for(int i=1;i<=n;i++) { if(!vis[i]) { que.push(i); sum++; } } for(int i=0;i<n;i++) { if(!que.empty()) { //printf("%d\n",que.front()); if(vis[num[i]]>1) { if(num[i]>que.front()) { vis[num[i]]--; num[i]=que.front(); que.pop(); } else { if(cnt[num[i]]==0) cnt[num[i]]=1; else { vis[num[i]]--; num[i]=que.front(); que.pop(); } } } } } printf("%d\n",sum); for(int i=0;i<n;i++) if(i<n-1) printf("%d ",num[i]); else printf("%d\n",num[i]); return 0; }

浙公网安备 33010602011771号