cf Codeforces Global Round 3 E. Earth Wind and Fire

题目链接:http://codeforces.com/contest/1148/problem/E

 

题意:

       给你2n个数,分别是n个a数组和n个b数组,现在你可以进行这样的变换,每次选择两个数,将它们一个+d一个-d,且2d要小于它们的差,问你能不能用这种操作将a数组变成b数组,如果可以给出操作的下标和要加的d。

做法:

        一开始的做法想简单了,就以为是a的当前最大值和最小值取出将a的min往b的min去做,但是这样的会很可能会超过2d的这个限制,所以要一边加一边找减,由于先经过的排序这样的话会避免出现问题。因为是一加一减且处理的数字是一样的所以总和必须不变这是限制条件。


#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=300005;
ll suma,sumb;
int b[maxn],n;
int ans1[maxn*5],ans2[maxn*5],ans3[maxn*5];
struct node{
    int id,v;
    node(){}
    node(int id,int v):id(id),v(v){}
    bool operator < (const node &a)const{
        return v<a.v;
    }
}e[maxn];
vector<node> ve;
int main(){
    scanf("%d",&n);
    rep(i,1,n){
        scanf("%d",&e[i].v);
        suma+=e[i].v; e[i].id=i;
    }
    rep(i,1,n){
        scanf("%d",&b[i]);
        sumb+=b[i];
    }
    if(suma!=sumb){
        return 0*printf("NO\n");
    }
    sort(b+1,b+1+n);
    sort(e+1,e+1+n);
    bool ok=true;
    int m=0;
    rep(i,1,n){
        if(!ok) break;
        int needadd=b[i]-e[i].v;
        if(needadd==0) continue;
        if(needadd>0) ve.push_back(node(e[i].id,needadd));
        else {
            while(needadd<0){
                if(ve.empty()){ok=false; break;}
                int la=ve.size()-1;
                int fin=min(-needadd,ve[la].v);
                ve[la].v-=fin;
                if(ve[la].v==0) ve.pop_back();
                needadd+=fin;
                m++;
                ans2[m]=e[i].id,ans1[m]=ve[la].id,ans3[m]=fin;
            }

        }
    }
    if(!ok||ve.size()) return 0*printf("NO\n");
    printf("YES\n%d\n",m);
    rep(i,1,m){
        printf("%d %d %d\n",ans1[i],ans2[i],ans3[i]);
    }


    return 0;
}

 

上一篇:LG1081 开车旅行


下一篇:C#常用功能函数小结(.NET 4.5)