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

    3295: [Cqoi2011]动态逆序对

    Time Limit: 10 Sec  Memory Limit: 128 MB

    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

    分析:若没有删除,直接树状数组即可;

       因为带删除,则需要动态修改;

       权值线段树套树状数组,这样修改后也可以查询对应逆序对个数;

       查询时二分原理;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    const int maxn=1e5+10;
    const int N=5e4+10;
    const int M=N*10*10;
    using namespace std;
    inline ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    inline ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    inline int id(int l,int r){return l+r|l!=r;}
    inline void umax(ll &p,ll q){if(p<q)p=q;}
    inline void umin(ll &p,ll q){if(p>q)p=q;}
    inline ll read()
    {
        ll x=0;int f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,k,t,s[M],ls[M],rs[M],lo[21],ro[21],rx[maxn],pos[maxn],d[maxn],a[maxn],b[maxn],sz;
    int get(int x){int ret=0;while(x)ret+=d[x],x-=x&(-x);return ret; }
    void add(int x){while(x<=n)d[x]++,x+=x&(-x); }
    void insert(int l,int r,int x,int &y,int z)
    {
        if(!y)y=++sz;
        s[y]=s[x]+1;
        if(l==r)return;
        int mid=l+r>>1;
        ls[y]=ls[x],rs[y]=rs[x];
        if(z<=mid)insert(l,mid,ls[x],ls[y],z);
        else insert(mid+1,r,rs[x],rs[y],z);
    }
    void del(int x)
    {
        int y=pos[x];
        while(y<=n)
        {
            insert(1,n,rx[y],rx[y],x);
            y+=y&(-y);
        }
    }
    int ask_more(int z)
    {
        int ret=0,l=1,r=n,i;
        while(l!=r)
        {
            int mid=l+r>>1;
            if(z<=mid)
            {
                rep(i,1,lo[0])ret-=s[rs[lo[i]]],lo[i]=ls[lo[i]];
                rep(i,1,ro[0])ret+=s[rs[ro[i]]],ro[i]=ls[ro[i]];
                r=mid;
            }
            else
            {
                rep(i,1,lo[0])lo[i]=rs[lo[i]];
                rep(i,1,ro[0])ro[i]=rs[ro[i]];
                l=mid+1;
            }
        }
        return ret;
    }
    int ask_less(int z)
    {
        int ret=0,l=1,r=n,i;
        while(l!=r)
        {
            int mid=l+r>>1;
            if(z>mid)
            {
                rep(i,1,lo[0])ret-=s[ls[lo[i]]],lo[i]=rs[lo[i]];
                rep(i,1,ro[0])ret+=s[ls[ro[i]]],ro[i]=rs[ro[i]];
                l=mid+1;
            }
            else
            {
                rep(i,1,lo[0])lo[i]=ls[lo[i]];
                rep(i,1,ro[0])ro[i]=ls[ro[i]];
                r=mid;
            }
        }
        return ret;
    }
    int gao(int x)
    {
        int ret=0,y,z;
        lo[0]=ro[0]=0,y=pos[x];
        while(y)
        {
            ro[++ro[0]]=rx[y];
            y-=y&(-y);
        }
        ret+=ask_more(x);
        lo[0]=ro[0]=0;
        y=pos[x],z=n;
        while(y)
        {
            lo[++lo[0]]=rx[y];
            y-=y&(-y);
        }
        while(z)
        {
            ro[++ro[0]]=rx[z];
            z-=z&(-z);
        }
        ret+=ask_less(x);
        return ret;
    }
    int main()
    {
        int i,j;
        ll ret=0;
        scanf("%d%d",&n,&m);
        rep(i,1,n)
        {
            scanf("%d",&a[i]);
            pos[a[i]]=i;
            add(a[i]);
            b[i]+=get(n)-get(a[i]);
            ret+=b[i];
        }
        memset(d,0,sizeof(d));
        for(i=n;i>=1;i--)
        {
            add(a[i]);
            b[i]+=get(a[i]-1);
        }
        rep(i,1,m)
        {
            printf("%lld
    ",ret);
            scanf("%d",&j);
            ret-=b[pos[j]]-gao(j);
            del(j);
        }
        return 0;
    }
  • 相关阅读:
    复制、删除、移动文件、获取文件的版本信息、更改文件属性,删除只读文件
    How to use the MQ?
    StreamReader、 StreamWriter
    我的第一个AJAX程序
    XML操作
    SQL 使用XML数据修改语言
    认识 ASP.NET 3.5 MVC 路由解析分析
    北京2008奥运会开幕式&闭幕式下载(NBCBT附字幕)
    认识 ASP.NET 3.5 MVC 路由 理解默认路由表
    每天都有新发现 2009年10月21日 Decimal 和存储过程OUTPUT
  • 原文地址:https://www.cnblogs.com/dyzll/p/6372291.html
Copyright © 2011-2022 走看看