CF #251 div2
2014-06-05 22:23:48
A,B两题直接水过(坑爹的是程序不鲁棒,被hack两次!)
C:
题意&思路:拆分一串数成k份,要求其中p份各自和为偶数,k-p份各自和为奇数。分析:奇数能转化成偶数(2奇凑1偶),而偶数不能凑成奇数,所以先考虑奇数总数是否大于k-p,再考虑到:如果奇数总数减去看k-p(需求数)为奇数的话,也是不行的(转化到偶数需要偶数个奇数);最后考虑到偶数总数加上多余的奇数/2仍小于p(需求数),也不行。所以把以上三种情况考虑了之后,剩下的情况一定是可行的,这点很有用。接下来就是关键的步骤:输出k-p-1个奇数(如果k-p-1<=0,不输出),留下一个奇数!再输出p-1个偶数(如果p-1<=0,不输出),留下一个偶数。为什么要各留下一个奇数一个偶数呢?好吧,先来考虑三种情况(1)p==0,k-p!=0,不需要偶数,只要奇数,这时如果之前把需要的奇数都输出了,那就会剩下一堆偶数没有处理,所以这时留下的奇数和偶数一起输出。(2)p!=0,k-p==0,不需要奇数,只要偶数,同理如果把偶数都输出了,会剩下一堆奇数没有处理,所以这时留下的奇数和偶数一起输出。(3)p!=0,k-p!=0,这时留下的一奇一偶显得有点多余,于是先把奇数输出,再把剩下的奇数偶数输出。(或者把偶数输出,剩下的奇数偶数输出)。
#include <cstdio> #include <iostream> using namespace std; int odd[100005],even[100005]; int main(){ int n,k,p,u,ocnt = 0,ecnt = 0,v; scanf("%d %d %d",&n,&k,&p); u = k - p; for(int i = 0; i < n; ++i){ scanf("%d",&v); if(v & 1) odd[ocnt++] = v; else even[ecnt++] = v; } if(ocnt < u || (ocnt - u) & 1 || ecnt + ((ocnt - u)>>1) < p){ printf("NO\n"); return 0; } printf("YES\n"); for(int i = 0; i < u - 1; ++i) printf("1 %d\n",odd[--ocnt]); for(int i = 0; i < p - 1; ++i){ if(ecnt) printf("1 %d\n",even[--ecnt]); else{ printf("2 %d %d\n",odd[ocnt - 1],odd[ocnt - 2]); ocnt -= 2; } } if(u && p) printf("1 %d\n",odd[--ocnt]); printf("%d",ocnt + ecnt); while(ocnt) printf(" %d",odd[--ocnt]); while(ecnt) printf(" %d",even[--ecnt]); puts(""); return 0; }
D:
题意&思路:贪心策略,已无力赘述。。。。有两个版本
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int maxn = 100000; long long n,m; long long a[maxn + 5],b[maxn + 5],ae[maxn + 5],be[maxn + 5],amin = 1000000001,bmax = 0; bool cmpmax(int a,int b){ return a > b; } bool cmpmin(int a,int b){ return a < b; } int main(){ scanf("%I64d %I64d",&n,&m); for(int i = 1; i <= n; ++i){ scanf("%I64d",&a[i]); amin = min(amin,a[i]); } for(int i = 1; i <= m; ++i){ scanf("%I64d",&b[i]); bmax = max(bmax,b[i]); } sort(a + 1,a + n + 1,cmpmin); sort(b + 1,b + m + 1,cmpmax); ae[n] = n; be[m] = m; for(int i = n - 1; i >= 1; --i){ if(a[i] == a[i + 1]) ae[i] = ae[i + 1]; else ae[i] = i; } for(int i = m - 1; i >= 1; --i){ if(b[i] == b[i + 1]) be[i] = be[i + 1]; else be[i] = i; } long long ap = 1,bp = 1;//positions long long t1,t2,l1 = ae[1],l2 = be[1],sum = 0; while(amin < bmax){ if(l1 <= l2){ if(l1 < n){ amin = min(a[ae[ap] + 1],bmax); sum += l1 * (amin - a[ap]); ap = ae[ap] + 1; l1 = ae[ap]; } else{ //l1 == n sum += n * (bmax - amin); amin = bmax; } } else{ if(l2 < m){ bmax = max(b[be[bp] + 1],amin); sum += l2 * (b[bp] - bmax); bp = be[bp] + 1; l2 = be[bp]; } else{ sum += m * (bmax - amin); bmax = amin; } } } cout << sum <<endl; return 0; }
#include <iostream> #include <algorithm> using namespace std; long long a[100005],b[100005],sum; bool cmp1(long long a,long long b){ return a < b;} bool cmp2(long long a,long long b){ return a > b;} int main(){ int n,m; cin>>n>>m; for(int i=0;i<n;++i) cin>>a[i]; for(int i=0;i<m;++i) cin>>b[i]; sort(a,a+n,cmp1); sort(b,b+m,cmp2); for(int i=0;i<min(n,m);++i) if(b[i]>a[i]) sum += b[i]-a[i]; cout<<sum<<endl; return 0; }