全球轮3——cf1148

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()<<'\n';
    for(int i=0;i<ans.size();i++)
        cout<<ans[i].first<<" "<<ans[i].second<<'\n';
}    
View Code

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()<<'\n';
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<" ";
}        
View Code

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()<<'\n';
    for(int i=0;i<ans[0].size();i++)
        cout<<ans[0][i]<<" "<<ans[1][i]<<" "<<ans[2][i]<<'\n';
}

F——待补

 

posted on 2019-06-05 10:02  zsben  阅读(210)  评论(0编辑  收藏  举报

导航