zoukankan      html  css  js  c++  java
  • 全球轮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()<<'
    ';
        for(int i=0;i<ans.size();i++)
            cout<<ans[i].first<<" "<<ans[i].second<<'
    ';
    }    
    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()<<'
    ';
        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()<<'
    ';
        for(int i=0;i<ans[0].size();i++)
            cout<<ans[0][i]<<" "<<ans[1][i]<<" "<<ans[2][i]<<'
    ';
    }

    F——待补

  • 相关阅读:
    最长有效括号
    C++ 环形缓存区的实现
    vector的原理与底层实现
    聚合分析与分组
    求两个数的最大公约数
    单例模式
    工厂方法模式
    责任链模式
    适配器模式
    策略模式
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10977992.html
Copyright © 2011-2022 走看看