• bzoj 3295 动态逆序对 (三维偏序,CDQ+树状数组)


    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3295

    思路:

    可以将这道题看成倒着插入,这样就可以转化成求逆序对数,用CDQ分治降维,正反用树状数组求两遍逆序对就好了。

    这道题还可以用在线的树套树或者可持久化线段树来写。。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 2e5+10;
    struct node{
         int t,x,y;
         int kind,id;
         node() {}
         node(int a,int b,int c,int d,int e = 0):t(a),x(b),y(c),kind(d),id(e){}
         bool operator < (const node &k) const {
             if(x == k.x) return y<k.y;
             return x < k.x;
         }
    };
    int n,m,a[M],pos[M],x,c[M],tim,len;
    node q[M],t[M];
    ll ans[M];
    void add(int x,int val){
         while(x <= n){
             c[x] += val;
             x += (x&-x);
         }
    }
    
    int getsum(int x){
        int sum = 0;
        while(x){
            sum += c[x];
            x -= (x&-x);
        }
        return sum;
    }
    
    void cdq(int l,int r){
        if(l == r) return ;
        int mid = (l + r) >> 1;
        for(int i = l;i <= r;i ++){
            if(q[i].t <= mid) add(q[i].y,q[i].kind);
            else ans[q[i].id] += q[i].kind*(getsum(n) - getsum(q[i].y));
        }
        for(int i = l;i <= r;i ++)
            if(q[i].t <= mid) add(q[i].y,-q[i].kind);
    
        for(int i = r;i >= l;i --){
            if(q[i].t <= mid) add(q[i].y,q[i].kind);
            else ans[q[i].id] += q[i].kind*getsum(q[i].y-1);
        }
        for(int i = l;i <= r;i ++)
            if(q[i].t <= mid) add(q[i].y,-q[i].kind);
    
        int L = l,R = mid+1;
        for(int i = l;i <= r;i ++){
            if(q[i].t <= mid) t[L++] = q[i];
            else t[R++] = q[i];
        }
        for(int i = l;i <= r;i ++) q[i] = t[i];
        cdq(l,mid); cdq(mid+1,r);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i ++){
            scanf("%d",&a[i]);
            pos[a[i]] = i; q[++len] = node(++tim,i,a[i],1,0);
        }
        for(int i = 1;i <= m;i ++){
            scanf("%d",&x);
            q[++len] = node(++tim,pos[x],x,-1,i);
        }
        sort(q+1,q+1+len);
        cdq(1,len);
        for(int i = 1;i <= m;i ++){
            ans[i] += ans[i-1];
            printf("%lld
    ",ans[i-1]);
        }
        return 0;
    }
  • 相关阅读:
    轻松管理您的网络password
    尝到awk
    重载虚函数的相关问题
    阿赫亚web安全JSON
    SplitContainer如何实现左侧导航,正确显示和导航内容
    POJ 3450 Corporate Identity KMP解决问题的方法
    virtio-blk分析
    JavaScript权威指南科03章 种类、值和变量(1)
    iOS开展-Xcode技巧总结(持续更新)
    POI设置边框
  • 原文地址:https://www.cnblogs.com/kls123/p/9523242.html
Copyright © 2020-2023  润新知