c——贪心构造题
/* 1 [n/2+1,n] 2 [n/2+2,n] ... n/2 [n,n] n/2+1 [1,1] n/2+2 [1,2] ... n [1,n/2] ai要换到位置ai上,用1,n作为跳板 从2开始,把值为i的移动到位置i上 */ #include<bits/stdc++.h> using namespace std; #define maxn 500005 int n,a[maxn],pos[maxn]; vector<pair<int,int> >ans; void change(int pos1,int pos2){//交换两个位置 ans.push_back(make_pair(pos1,pos2)); swap(pos[a[pos1]],pos[a[pos2]]); swap(a[pos1],a[pos2]); } void calc(int pos1,int pos2){ if(pos1>pos2)swap(pos1,pos2); if(abs(pos1-pos2)>=n/2) change(pos1,pos2); else { if(pos1<=n/2 && pos2<=n/2){ change(pos1,n); change(n,pos2); change(pos1,n); } else if(pos1>n/2 && pos2>n/2){ change(pos1,1); change(1,pos2); change(pos1,1); } else { change(1,pos2); change(pos1,n); change(1,n); change(1,pos2); change(pos1,n); } } } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i],pos[a[i]]=i; if(pos[1]!=1) calc(pos[1],1); if(pos[n]!=n) calc(pos[n],n); for(int i=2;i<=n-1;i++){ if(pos[i]==i)continue; else calc(pos[i],i); } if(a[1]!=1) ans.push_back(make_pair(1,n)); cout<<ans.size()<<' '; for(int i=0;i<ans.size();i++) cout<<ans[i].first<<" "<<ans[i].second<<' '; }
D——贪心+排序
#include<bits/stdc++.h> using namespace std; struct Node{int a,b,id;}p[300005]; int cmp1(Node a,Node b){return a.b>b.b;} int cmp2(Node a,Node b){return a.b<b.b;} int n; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>p[i].a>>p[i].b,p[i].id=i; sort(p+1,p+1+n,cmp1); vector<int> v; int la=-1; for(int i=1;i<=n;i++){ if(p[i].a>=la&&la!=-1 || p[i].a>=p[i].b)continue; la=p[i].b; v.push_back(p[i].id); } sort(p+1,p+1+n,cmp2); vector<int>vv; la=-1; for(int i=1;i<=n;i++){ if(p[i].a<=la&&la!=-1 || p[i].a<=p[i].b)continue; la=p[i].b; vv.push_back(p[i].id); } if(v.size()<vv.size()) swap(v,vv); cout<<v.size()<<' '; for(int i=0;i<v.size();i++) cout<<v[i]<<" "; }
E——推不等式+构造+双指针
/* 分别排序后用双指针分别指向需要向右拉的,需要向左拉的 有解的两个条件: 1.和相等 2.差的前缀必须<=0,因为a[i]-b[i]的前缀和如果>0,由于前面的只能往右拉,所以无解 同时:a[i]<=a[j],b[i]<=b[j],并且 a[i]<=b[i],a[j]>=b[j], (b[i]-a[i])+(a[j]-b[j])<=a[j]-a[i] min(b[i]-a[i],a[j]-b[j])<=(a[j]-a[i])/2 所以双指针移动的贪心正确 */ #include<bits/stdc++.h> #include<vector> using namespace std; #define maxn 500005 #define ll long long ll n; struct Node{ ll id,x; }a[maxn],b[maxn]; ll dif[maxn],suma,sumb; vector<ll>ans[3]; int cmp(Node a,Node b){return a.x<b.x;} int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i].x,suma+=a[i].x,a[i].id=i; for(int i=1;i<=n;i++)cin>>b[i].x,sumb+=b[i].x; if(suma!=sumb){puts("NO");return 0;} sort(a+1,a+1+n,cmp);sort(b+1,b+1+n,cmp);//从小到大排序,可以保证最左边的a[i]一定是被向右拉的 ll tmp=0; for(int i=1;i<=n;i++){ dif[i]=a[i].x-b[i].x; tmp+=dif[i]; if(tmp>0){puts("NO");return 0;} } for(int i=1,j=1;i<=n;i++){ while(dif[i]<0){ while(dif[j]<=0)//找到第一个可以向左拉的 j++; int d=min(-dif[i],dif[j]);//用较小的差去拉近 ans[0].push_back(a[i].id); ans[1].push_back(a[j].id); ans[2].push_back(d); dif[i]+=d;dif[j]-=d; } } puts("YES"); cout<<ans[0].size()<<' '; for(int i=0;i<ans[0].size();i++) cout<<ans[0][i]<<" "<<ans[1][i]<<" "<<ans[2][i]<<' '; }
F——待补