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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值