Codeforces Round #402 (Div. 2)
做了一套模拟contest,前三道题顺风顺水,第四道题卡懵逼了,不应该不应该。
题目大意:有两组,每组里面都有n个人,每个人都有一个评价分数1到5,你每次能从两组人中
分别挑选一个人,然后交换,问你使两组人每个分数评价的人都相同最少需要交换多少次。不能完成
输出-1。
思路:统计每组需要多少人需要到对面去,再除2就好了。
#include<bits/stdc++.h> using namespace std; int vis[2][6]; int n; int main() { cin>>n; for(int i=1;i<=n;i++) { int g; scanf("%d",&g); vis[0][g]++; } for(int i=1;i<=n;i++) { int g; scanf("%d",&g); vis[1][g]++; } int ans=0; for(int i=1;i<=5;i++) { int sum=vis[1][i]+vis[0][i]; if(sum&1) { puts("-1"); return 0; } ans+=sum/2-min(vis[1][i],vis[0][i]); } if(ans&1) puts("-1"); else cout<<ans/2<<endl; return 0; }
题目大意:给你一个数n 和 一个数 k ,要求删除n中个位数中的某几个,使其能被 10^k 整除,问你
最少删除几个数。
思路:直接模拟,从最低位开始。
#include<bits/stdc++.h> using namespace std; char s[20]; int k; int main() { scanf("%s %d",s,&k); int len=strlen(s); int ans=0,cnt=0; for(int i=len-1;i>=0;i--) { if(s[i]=='0') cnt++; if(cnt==k) break; if(s[i]!='0') ans++; } if(cnt==k) printf("%d\n",ans); else printf("%d\n",len-1); return 0; }
题目大意:有一个商店有n个商品,价格分别为p1[ i ],1天后的价格为p2[ i ],你今天必须买 k 件商品
1天后把剩下没买过的全部买掉,问你最少花费多少钱。
思路:简单贪心,先将差价排序,前k个必取,后面的如果价差为负就取。
#include<bits/stdc++.h> using namespace std; const int N=2*1e5+5; struct node { int c,id; bool operator < (const node &t)const { return c<t.c; } }w[N]; int a[N],b[N],n,k; bool vis[N]; int main() { cin>>n>>k; for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); for(int i=0;i<n;i++) w[i].c=a[i]-b[i],w[i].id=i; sort(w,w+n); int ans=0; for(int i=0;i<n;i++) { if(i<k || w[i].c<0) ans+=a[w[i].id],vis[w[i].id]=1; } for(int i=0;i<n;i++) { if(!vis[i]) ans+=b[i]; } cout<<ans<<endl; return 0; }
题目大意:给你两个字符串 t 和 p 且 | t | > | p |,现在我们要按给定的顺序一个一个地拿掉 t 中的字符,
问你最大拿掉几个字符,p 还是 t 的子序列。
我模拟contest的时候一直看错题意,以为这个子序列的意思是,必须连在一起。还有就是我把这个题
想的太麻烦了,我刚开始想的时候如果将 t 的字符一个一个拿掉很难判断目前为止到底是不是最大值,
所以我就想从后往前一个一个按顺序插入,第一次碰到满足的情况就是答案了,然后还傻逼一样地写
了一个链表。。。。。。。。。。。我他妈我都服了我自己了,连二分搜索都不会了。。。。。。。
思路:直接二分最大值,可以O( n )地判断当前的 t 序列的子序列中有没有 p ,我们可以用一个w[ i ]
数组表示,第 i 个数是第几个被拿掉的。
#include<bits/stdc++.h> using namespace std; const int N=2*1e5+5; char t[N],p[N]; int a[N],w[N],n,m; bool check(int x) { int j=1; for(int i=1;i<=n;i++) { if(w[i]>x && t[i]==p[j]) j++; } if(j>m) return true; else return false; } int main() { scanf("%s%s",t+1,p+1); n=strlen(t+1); m=strlen(p+1); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); w[a[i]]=i; } int l=0,r=n,ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(mid)) { ans=max(ans,mid); l=mid+1; } else r=mid-1; } cout<<ans<<endl; return 0; }
ps : 满足某种条件的最大值最小值,优先考虑二分!!!!!!!!!!!!!