题目链接:
http://codeforces.com/contest/1148/problem/E
题意:
给出两个长度为$n$的序列,将第一个序列变成第二个序列,顺序不重要,只需要元素完全相同即可
只有一种修改操作
- $a_i=a_i+d,a_j=a_j-d$满足 $a_j-a_i\geq 2 \cdot d$
数据范围:
$1\leq n\leq 3e^{5}$
分析:
先说结论:
- 对$a,b$数组排序,结果一定是$a_i$变成$b_i$,也就是一一对应的关系
- 有些数需要增加,有些数需要减少,第一个增加的数和第一个减少的数对应操作
- 如果(需要减少的数的目标位置)小于(需要增大的数的目标位置),那么就输出$NO$
在草稿纸上模拟几次就好了,$QAQ$
ac代码:
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=3e5+10;
struct Ans
{
int a,b,c;
}ans[maxn*5];
int cnt;
struct Move
{
int id,now,to;
bool operator <(const Move &a)const
{
if(to==a.to)return id<a.id;
return to<a.to;
}
};
pa a[maxn];
int b[maxn];
set<Move>se1,se2;
int main()
{
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].first);
a[i].second=i;
}
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
sort(a+1,a+1+n);
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
//cout<<a[i].first<<" "<<b[i]<<endl;
if(a[i].first<b[i])
se1.insert((Move){a[i].second,b[i]-a[i].first,b[i]});
else if(a[i].first>b[i])
se2.insert((Move){a[i].second,a[i].first-b[i],b[i]});
//cout<<se1.size()<<" "<<se2.size()<<endl;
}
while(1)
{
//cout<<se1.size()<<" "<<se2.size()<<endl;
//cout<<"sadf0"<<endl;
if(se1.size()==0&&se2.size()==0)break;
if(se1.size()==0||se2.size()==0)
{
printf("NO\n");
return 0;
}
Move x=(*se1.begin());
Move y=(*se2.begin());
if(x.to>y.to)
{
printf("NO\n");
return 0;
}
// cout<<x.id<<" "<<y.id<<endl;
se1.erase(x);
se2.erase(y);
if(x.now==y.now)
{
ans[++cnt]=(Ans){x.id,y.id,x.now};
}
else if(x.now<y.now)
{
ans[++cnt]=(Ans){x.id,y.id,x.now};
y.now-=x.now;
se2.insert(y);
}
else if(x.now>y.now)
{
ans[++cnt]=(Ans){x.id,y.id,y.now};
x.now-=y.now;
se1.insert(x);
}
}
printf("YES\n");
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
return 0;
}