zoukankan      html  css  js  c++  java
  • [CQOI2011]动态逆序对

    原题点这里

    我们发现这道题可以用树状数组套权值线段树(主席树的一些优化)

    (不会点这里) 我感觉我这样写下去朴素的主席树要不会写了。

    我们发现一个点对答案的贡献有两部份,在其之前比其大的,在其之后比他小的。

    我们每次删除一个点,把其对答案的贡献减去就好了。

    我们考虑一下这样所费的空间,我们知道删除时是按原路径遍历,不会加空间。我们只考虑加点的空间开销。我们每次加一个点,期望我们访问log n个线段树,每个线段树log n个点,那么就是O(nlog n^2)的空间复杂度。5W*16*16=1280W?事实证明是不到的,因为我们不是每次都会开出logN^2个点。反正能开多大就开多大吧。

    就酱紫。

    #include<bits/stdc++.h>
    #define N 8500007 
    #define M 100007
    #define Mid (l+r>>1)
    #define L(x) (x&-x)
    #define LL long long
    using namespace std;
    int siz[N],ls[N],rs[N],si,n,tot,ne[M],m,X,a[M],n2[M],n3[M],to1;
    LL ans;
    #define sight(c) ('0'<=c&&c<='9')
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(c);c=getchar())x=x*10+c-48;
    }
    void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
    inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
    '); }
    void ins(int l,int r,int no,int q,int dla){
        siz[no]+=dla; if (l==r) return;
        if (Mid>=q) {if (!ls[no]) ls[no]=++si;ins(l,Mid,ls[no],q,dla);}
        else {if (!rs[no]) rs[no]=++si;ins(Mid+1,r,rs[no],q,dla);}
    }
    void add(int x,int i,int dla){for (;x<=n;x+=L(x)) ins(1,n,x,i,dla);}
    int ask(int l,int r,int q){
        if (l==r) return 0;
        if (Mid<q)  {
            for (int i=1;i<=tot;i++) ne[i]=rs[ne[i]]; return ask(Mid+1,r,q);
        }
        int sum=0;
        for (int i=1;i<=tot;i++) sum+=siz[rs[ne[i]]],ne[i]=ls[ne[i]];
        return sum+ask(l,Mid,q);
    }
    int Ask(int l,int r,int q){
        if (l==r) return 0;
        if (q<=Mid) {
            for (int i=1;i<=tot;i++) n2[i]=ls[n2[i]];
            for (int i=1;i<=to1;i++) n3[i]=ls[n3[i]]; return Ask(l,Mid,q); 
        }
        LL sum=0;
        for (int i=1;i<=tot;i++) sum-=siz[ls[n2[i]]],n2[i]=rs[n2[i]];
        for (int i=1;i<=to1;i++) sum+=siz[ls[n3[i]]],n3[i]=rs[n3[i]];
        return sum+Ask(Mid+1,r,q);
    }
    int query(int r,int val){
        for (tot=0;r;r-=L(r)) ne[++tot]=r;
        return ask(1,n,val);
    }
    int Query(int r,int val){
        int y=n;
        for (tot=0;r;r-=L(r)) n2[++tot]=r;
        for (to1=0;y;y-=L(y)) n3[++to1]=y;
        return Ask(1,n,val);
    }
    int main () {
        freopen("inverse.in","r",stdin);
        freopen("inverse.out","w",stdout);
        read(n); read(m); si=n;
        for (int i=1;i<=n;i++) 
            read(X),add(i,X,1),a[X]=i;
        for (int i=1;i<=n;i++) 
          ans+=query(a[i],i); 
        while (m--) {
            writeln(ans);read(X);
            ans-=Query(a[X],X)+query(a[X],X);
            add(a[X],X,-1);
        }return 0;
    }
  • 相关阅读:
    二:虚拟游戏摇杆
    一:AndEngine的小例子
    打造属于自己的安卓Metro界面
    linux设备驱动第四篇:驱动调试方法
    C# 二叉查找树实现
    初识 Angular 体会
    C# 霍夫曼二叉树压缩算法实现
    TypeScript笔记[5]泛型+Dictionary 转
    Axiom3D学习日记 5.Frame Listeners, and Input Handling
    Axiom3D学习日记 4.地形,天空,雾
  • 原文地址:https://www.cnblogs.com/rrsb/p/8312971.html
Copyright © 2011-2022 走看看