codeforces 1148E- Earth Wind and Fire
传送门:QAQQAQ
题意:给你一个数组,你可以进行一个操作:取a[i],a[j],且a[i]<a[j],令d*2<=a[j]-a[i],随后令a[i]+=d;a[j]-=d。问最后能否形成另一数组b,并输出方案
思路:先考虑不可能的情况,若两边和不相等,则肯定不可能。如果a数组前k个数的和大于b数组前k个数的和,则不可能,因为我们可以把前k个数看成一个整体,它在操作中只能变大不能变小。
若可能,则从小到大搜一个个消耗即可
……然而我最简单的消耗之前都写错了……
之前是这样的:把a[i]-b[i]>0的分为X组,a[i]-b[i]<0的分为Y组,然后各组加减消耗(当时居然还按照差排了个序!!!)。却没有想到X组中需要减的数可能比Y组中需要加的数还要小,因为再次排序完全打乱了从小到大的顺序
…………结果就是——比赛后删掉sort语句就AC了…………
略简洁代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int inf=(int)(2e9); 5 const ll INF=(ll)(5e18); 6 const int N=450010; 7 8 ll n,sa=0,sb=0; 9 ll s1=0,s2=0,c[N]; 10 struct node 11 { 12 ll x,id; 13 }fa[N],fb[N],a[N],b[N]; 14 vector<ll> v[3]; 15 16 bool cmp(node p,node q) 17 { 18 if(p.x==q.x) return p.id<q.id; 19 return p.x<q.x; 20 } 21 22 int main() 23 { 24 scanf("%lld",&n); 25 for(int i=1;i<=n;i++) 26 { 27 scanf("%lld",&a[i].x); 28 a[i].id=i; 29 sa+=a[i].x; 30 } 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%lld",&b[i].x); 34 b[i].id=i; 35 sb+=b[i].x; 36 } 37 if(sa!=sb) 38 { 39 puts("NO"); 40 return 0; 41 } 42 sort(a+1,a+n+1,cmp); 43 sort(b+1,b+n+1,cmp); 44 sa=0; sb=0; 45 for(int i=1;i<=n;i++) 46 { 47 c[i]=a[i].x-b[i].x; 48 sa+=a[i].x; sb+=b[i].x; 49 if(sa>sb) 50 { 51 puts("NO"); 52 return 0; 53 } 54 } 55 puts("YES"); 56 ll ans=0; 57 for(int i=1,j=1;i<=n;i++) 58 { 59 while(c[i]<0) 60 { 61 ans++; 62 while(c[j]<=0) j++; 63 ll d=min(-c[i],c[j]); 64 v[0].push_back(a[i].id); 65 v[1].push_back(a[j].id); 66 v[2].push_back(d); 67 c[i]+=d; c[j]-=d; 68 } 69 } 70 cout<<ans<<endl; 71 for(int i=0;i<ans;i++) printf("%lld %lld %lld\n",v[0][i],v[1][i],v[2][i]); 72 return 0; 73 }