• 区间翻转 归并排序 + 逆序对


    区间翻转

    这个题目如果不知道怎么用归并排序求逆序对还是很难想的,但是知道用归并排序求逆序对也不是一个很好写的题目。

    注意题目是每一个数只出现一次!!!

    思路:

    整体求考虑每一次操作的影响。

    因为每次操作都是2的幂次,那么我们先求出划分成(2^x) 块的每一个块内的逆序对之和,这个可以用归并排序做,所以假设 (dp[x]) 表示每一个块大小是 (2^x) 次方的所有块逆序对之和(注意这个定义是大小是(2^x) 块),那么容易知道,一个块的逆序对+顺序对=(len*(len-1)/2) 这个 (len) 表示块的大小。

    接下来考虑如果要求划分成 $2^q $ 块,那么每块大小就是 (2^x = 2^n - 2^q) ,因为每块划分大小是 (2^x) 这样对更大的块和更小的块的影响是不同的,对比这个块更小的块的影响就是:顺序对变成逆序对,逆序对变成顺序对,对比这个块更大的块的影响是:变化的块顺序对逆序对交换,但是块与块直接的顺逆序对数量不变。

    最后得出来的式子就是:(f[i]) 表示 (2^i) (temp[i]) 表示这次操作未更新之前的 (dp[i])

    (i<=x)(dp[i] = f[i]*(f[i]-1)/2*f[n-i]-dp[i])

    (i>x)(dp[i] = dp[i]-temp[i-1]+dp[i-1])

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 3e6+10;
    ll a[maxn],temp[maxn],dp[40],f[40];
    ll merge(int pos,int l,int r){
        if(pos==0){ dp[pos] = 0;return 0;}
        ll ans = 0;
        int mid = (l+r)>>1;
        ans += merge(pos-1,l,mid);
        ans += merge(pos-1,mid+1,r);
        int now = 0,x = l,y = mid + 1;
        while(x<=mid||y<=r){
            if(x<=mid&&y<=r) {
                if(a[x]<=a[y]) temp[++now]=a[x],x++;
                else temp[++now]=a[y],y++,ans+=mid-x+1;
            }
            else if(x<=mid) temp[++now] = a[x],x++;
            else if(y<=r) temp[++now] = a[y],y++;
        }
        dp[pos] += ans;
        for(int i=l,j=1;i<=r&&j<=now;i++,j++) a[i] = temp[j];
        return ans;
    }
    
    void init(){
        f[0] = 1;
        for(int i=1;i<=22;i++) f[i]=f[i-1]*2;
    }
    int main(){
        init();
        int n,m;
        scanf("%d%d",&n,&m);
        int len = 1<<n;
        for(int i=1;i<=len;i++) scanf("%lld",&a[i]);
        merge(n,1,len);
        while(m--){
            int x;
            scanf("%d",&x);
            x = n-x;
            for(int i=0;i<=n;i++) temp[i] = dp[i];
            for(int i=0;i<=x;i++) dp[i] = f[n-i]*f[i]*(f[i]-1)/2-dp[i];
            for(int i=x+1;i<=n;i++) dp[i] = dp[i] - temp[i-1] + dp[i-1];
            printf("%lld
    ", dp[n]);
        }
        return 0;
    }
    
  • 相关阅读:
    【DL-2-2】卷积神经网络(CNN)--AlexNet、ZFNet、VGGNet、GoogleNet、ResNet
    Python3 错误和异常-(try/except/else/finally/raise/assert)
    生成器 Generators
    Map,Filter 和 Reduce
    装饰器
    目标检测:介绍及传统方法
    【ML-17-2】MCMC--马尔可夫蒙特卡罗方法(MH和Gibbs)
    如何在JDK1.8中愉快地处理日期和时间
    luogu1447 能量采集
    luogu1775 古代人的难题 打表找规律
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13627703.html
Copyright © 2020-2023  润新知