zoukankan      html  css  js  c++  java
  • BZOJ3295: [Cqoi2011]动态逆序对

    Description

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

    Input

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

    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)。
     
    边想边码了好久cdq都快忘了学啥忘啥
    考虑倒过来做,每次删除我们看做是插入,倒着过来做
    那么可以转化下问题问(x,y,pos),在第x次修改前,位置pos之前,大于值y的有几个,位置pos之后,小于y的有几个
    变成一个三维偏序问题,套个树状数组倒着做一遍求和就好了
    如果实在不会就看看代码吧还好我板子记得熟
    代码如下:
    //MT_LI
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m;
    typedef long long ll;
    struct CDQ{
        int x,v,d;
    }a[110000],t[110000],e[110000];
    int cc[110000];
    ll ans[61000];
    int lowbit(int x){return x&-x;}
    void change(int x,int d){while(x<=n)cc[x]+=d,x+=lowbit(x);}
    int getsum(int x){int sum=0;while(x)sum+=cc[x],x-=lowbit(x);return sum;}
    void cdq(int l,int r)
    {
        if(l==r)return ;
        int mid=(l+r)/2;
        cdq(l,mid),cdq(mid+1,r);
        int i=l,j=mid+1,p=l;
        while(i<=mid&&j<=r)
        {
            if(a[i].x<a[j].x)
                change(a[i].d,1),t[p++]=a[i++];
            else 
                ans[a[j].v]+=getsum(a[j].d),t[p++]=a[j++];
        }
        while(i<=mid)change(a[i].d,1),t[p++]=a[i++];
        while(j<=r)ans[a[j].v]+=getsum(a[j].d),t[p++]=a[j++];
        for(int j=l;j<=mid;j++)change(a[j].d,-1);
        for(int i=l;i<=r;i++)a[i]=t[i];
    }
    int d[110000];
    int pos[110000],v[110000];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&d[i]),d[i]=n-d[i]+1,pos[d[i]]=i;
        for(int i=n;i>=n-m+1;i--)
        {
            scanf("%d",&a[i].d);a[i].d=n-a[i].d+1;
            v[a[i].d]=1;a[i].v=n-i+1;a[i].x=pos[a[i].d];
        }
        int cnt=0;
        for(int i=1;i<=n;i++)
            if(!v[d[i]])
                a[++cnt].d=d[i],a[cnt].x=i,a[cnt].v=m;
        memcpy(e,a,sizeof(e));
        cdq(1,n);
        memcpy(a,e,sizeof(a));
        for(int i=1;i<=n;i++)
            a[i].d=n-a[i].d+1,a[i].x=n-a[i].x+1;
        cdq(1,n);
        
        for(int i=m;i>=1;i--)ans[i]+=ans[i+1];
        for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    SolrCloud阶段总结
    Solr总结
    机器学习算法与Python实践之(六)二分k均值聚类
    机器学习问题方法总结
    浅谈Kmeans聚类
    AVL树的算法思路整理
    Solr4.6从数据库导数据的步骤
    红黑树
    浅谈 Adaboost 算法
    POJ 1836 Alignment
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9753553.html
Copyright © 2011-2022 走看看