• CQOI2011 动态逆序对


    题目链接:戳我

    其实和lrj蓝书上面一个题一模一样呢QAQ

    回来再补树套树的写法吧,这里就先放上cdq分治——

    我们可以先统计出总共的,然后再对每一步统计删去的逆序对个数。

    考虑删去一个数会影响哪些呢,首先肯定时间戳要比它小qwq(这样才能保证应该在它前面的操作都进行了),然后因为cdq分治是只有一边对另一边的贡献,所以要分类讨论:

    • (pos_i<pos_j)&&(val_i>val_j)
    • (pos_i>pos_j)&&(val_i<val_j)

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    #define int long long
    using namespace std;
    int n,m,cnt;
    int tree[MAXN<<2],pos[MAXN],ans[MAXN];
    struct Node{int ti,pos,val,op;}node[MAXN<<1];
    inline bool cmp(struct Node x,struct Node y){return x.pos<y.pos;}
    inline void add(int x,int k)
    {
        for(int i=x;i<=n;i+=i&(-i))
            tree[i]+=k;
    }
    inline int query(int x)
    {
        int cur_ans=0;
        for(int i=x;i;i-=i&(-i))
            cur_ans+=tree[i];
        return cur_ans;
    }
    inline void clear(int x)
    {
        for(int i=x;i<=n;i+=i&(-i))
            tree[i]=0;
    }
    inline void cdq(int l,int r)
    {
        if(l==r) return;
        int mid=(l+r)>>1;
        cdq(l,mid),cdq(mid+1,r);
        sort(&node[l],&node[mid+1],cmp);
        sort(&node[mid+1],&node[r+1],cmp);
        int i=l;
        for(int j=mid+1;j<=r;j++)
        {
            while(i<=mid&&node[i].pos<=node[j].pos) add(node[i].val,node[i].op),i++;
            ans[node[j].ti]+=node[j].op*(query(n)-query(node[j].val));
        }
        for(int j=l;j<i;j++) clear(node[j].val);
        i=mid;
        for(int j=r;j>=mid+1;j--)
        {
            while(i>=l&&node[i].pos>=node[j].pos) add(node[i].val,node[i].op),i--;
            ans[node[j].ti]+=node[j].op*(query(node[j].val-1));
        }
        for(int j=mid;j>i;j--) clear(node[j].val);
    }
    signed main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%lld",&x);
            pos[x]=i;
            node[++cnt]=(Node){0,i,x,1};
        }
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%lld",&x);
            node[++cnt]=(Node){i,pos[x],x,-1};
        }
        cdq(1,cnt);
        for(int i=1;i<=m;i++) ans[i]+=ans[i-1];
        for(int i=0;i<m;i++) printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    react开发环境准备
    react介绍
    课程大纲
    Proving Equivalences HDU-2767 (tarjan缩点)
    tarjan求强连通分量 + 缩点 + 求割点割边
    树的重心(性质+模版)
    Educational Codeforces Round 93 (Rated for Div. 2)(A B C D)
    Friend-Graph HDU
    Codeforces Round #665 (Div. 2) (A B C D E)
    Matrix Again HDU
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10826178.html
Copyright © 2020-2023  润新知