返回顶部

2021 CCPC桂林站 D - Assumption is All You Need (贪心)

D. Assumption is All You Need

  • 题意:给你两个长度为\(n\)的数组\(A\)\(B\),每次可以交换\(A\)中的逆序对,问你\(A\)能否通过操作得到\(B\)

  • 题解:从后往前遍历,贪心策略是,越大的数在越前面越好,首先\(A_i\)一定不大于\(B_i\),不然gg,先确定\(B_i\)\(A\)中的位置\(p\),我们要交换\((a_p,a_i)\),但不能直接交换,否则\([p+1,i-1]\)这些位置上的数如果有大于\(a_i\)的,在交换之后就不能在移动到\(p\)这个位置了,这和我们的贪心策略相违背,所以我们在这个过程中需要不断地将最大的\(a_j(a_i<a_j<b_i,j\in[p+1,i-1])\)往前移,可以用后缀记录最大值,然后push进答案即可,具体的看代码应该就能理解了.

  • 题解

    #include <bits/stdc++.h>
    using namespace std;
    #define PII pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define ll long long
    #define ull unsigned long long
    #define PLL pair<ll,ll>
    const int N=10000010;
    const int mod=1e9+7;
    const int INF=0x3f3f3f3f;
    
    int n;
    int pos[N],a[N],b[N];
    int suf_mx[N];
    vector<PII> ans;
    
    int main(){
        int _;
        scanf("%d",&_);
        while(_--){
            scanf("%d",&n);
            ans.clear();
            for(int i=1;i<=n;++i) scanf("%d",&a[i]),pos[a[i]]=i;
            for(int i=1;i<=n;++i) scanf("%d",&b[i]);
            bool flag=true;
            for(int i=n;i>=1;--i){
                if(a[i]==b[i]) continue;
                if(a[i]>b[i]){
                    flag=false;
                    break;
                }
                int p=pos[b[i]];
                for(int j=1;j<=n+1;++j) suf_mx[j]=0; 
                suf_mx[i]=i;
                for(int j=i-1;j>=p;--j){
                    if(a[j]<b[i]){
                        if(a[j]>a[suf_mx[j+1]]) suf_mx[j]=j;
                        else suf_mx[j]=suf_mx[j+1];
                    }
                    else suf_mx[j]=suf_mx[j+1];
                }
                while(p<i){
                    int x=p,y=suf_mx[p+1];
                    ans.pb({x,y});
                    swap(a[x],a[y]);
                    pos[a[x]]=x;
                    pos[a[y]]=y;
                    p=suf_mx[p+1];
                }
            }
            if(!flag) puts("-1");
            else{
                printf("%d\n",(int)ans.size());
                for(auto w:ans) printf("%d %d\n",w.fi,w.se);
            }
        }
        return 0;
    }
    
    
     
    
posted @ 2021-11-16 11:06  Rayotaku  阅读(460)  评论(0编辑  收藏  举报