• BZOJ 3295: [Cqoi2011]动态逆序对 CDQ分治


    3295: [Cqoi2011]动态逆序对


    Description

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    Input

    输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
     

    Output

     
    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    Sample Input

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    Sample Output

    5
    2
    2
    1

    样例解释
    (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

    HINT

    N<=100000 M<=50000

    Source

     题解:
      CDQ分治第一题
     
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 1e5+10, M = 1e3+20,inf = 2e9;
    
    LL ans[N];
    int n,m,c[N],mp[N];
    struct ss{
        int t,x,y;
        bool operator < (const ss &r) const {
            return x == r.x? y < r.y : x < r.x;
        }
    }a[N],t[N];
    int cmp(ss s1,ss s2) {
        return s1.t==s2.t?s1.x < s2.x:s1.t<s2.t;
    }
    void add(int x,int cc) {
        for(int i = x; i <= n; i += i & (-i)) c[i] += cc;
    }
    int sum(int x) {
        int s = 0;
        for(int i = x; i; i -= i&(-i)) s += c[i];
        return s;
    }
    void cdq(int l,int r) {
        if(l == r) return ;
        int md = (l+r)>>1;
        cdq(l,md),cdq(md+1,r);
        int i = l, j = md+1,p = l;
        while(i<=md||j<=r) {
            if(j>r||(i<=md&&a[i] < a[j])) add(a[i].y,1),t[p++]=a[i++];
            else ans[a[j].t] += sum(n) - sum(a[j].y),t[p++]=a[j++];
        }
        for(int i = l; i <= md; ++i) add(a[i].y,-1);
        for(int i = l; i <= r; ++i) a[i] = t[i];
        for(int i = r; i >= l; --i) {
            if(a[i].t<=md) add(a[i].y,1);
            else ans[a[i].t] += sum(a[i].y);
        }
        for(int i = l; i <= r; ++i)
            if(a[i].t<=md) add(a[i].y,-1);
    }
    int main() {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; ++i) {
            int x;
            scanf("%d",&x);
            a[i].t =  0;
            a[i].x =  i;
            a[i].y =  x;
            mp[x] = i;
        }
        int Tim = n;
        for(int i = 1; i <= m; ++i) {
            int x;
            scanf("%d",&x);
            a[mp[x]].t = Tim--;
        }
        for(int i = 1; i <= n; ++i) {
            if(!a[i].t) a[i].t = Tim--;
        }
        sort(a+1,a+n+1,cmp);
        cdq(1,n);
        for(int i = 1; i <= n; ++i) ans[i] += ans[i-1];
        for(int i = n; i >= n-m+1; i--) printf("%lld
    ",ans[i]);
        return 0;
    }
      
  • 相关阅读:
    Linux系统配置静态ip
    爬虫之如何找js入口(一)
    asyncio动态添加任务
    关于python导包问题
    python动态添加属性
    requests模块
    反selenium关键字
    PIL模块
    openxlsx模块
    CSV
  • 原文地址:https://www.cnblogs.com/zxhl/p/7170872.html
Copyright © 2020-2023  润新知