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)。

    终于实战了一下分治(o゚v゚)ノ
    先确定基本的思路:
    我们只要算出出针对每个数他被删除时破坏了多少对逆序对即可
    首先每个数开始时参与了多少个逆序对时很容易算出来的
    那么我们只要对每个数而言计算删它之前有多少已经被删了的数是在他前面比他大,或者在他后面比他小
    而这个东西就可以分治了。
    比如说我们按照时间劈成两个区间
    这样就只用统计左区间对右区间的影响就好了
    事先用位置进行排序再处理就可以了~
    具体看看码吧(终于自己做出来一道233ˋ( ° ▽、° ) 
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define ll long long
     5 #define maxn 100005
     6 #define maxm 50005
     7 using namespace std;
     8 int n,m;
     9 int c[maxn],a[maxn],s[maxn],e[maxm],pos[maxn],t[maxm];
    10 ll ans;
    11 void add(int x,int z){while(x<=n){c[x]+=z;x+=x&(-x);}}
    12 int sum(int x){int ans=0;while(x){ans+=c[x];x-=x&(-x);}return ans;}
    13 int query(int l,int r){if(l>r)return 0;return sum(r)-sum(l-1);}
    14 bool cmp(int x,int y){return pos[x]<pos[y];}
    15 void solve(int l,int r){
    16     if(l==r)return;
    17     int mid=(l+r)/2;
    18     solve(l,mid);solve(mid+1,r);
    19     int tx=l,ty=mid+1;
    20     while(tx<=mid||ty<=r){
    21         if(ty>r||(tx<=mid&&pos[e[tx]]<pos[e[ty]]))add(e[tx++],1);
    22         else{s[e[ty]]-=query(e[ty],n);ty++;}
    23     }
    24     for(int i=l;i<=mid;i++)add(e[i],-1);
    25     tx=mid,ty=r;
    26     while(tx>=l||ty>=mid+1){
    27         if((ty<mid+1)||(tx>=l&&pos[e[tx]]>pos[e[ty]]))add(e[tx--],1);
    28         else{s[e[ty]]-=query(1,e[ty]);ty--;}
    29     }
    30     for(int i=l;i<=mid;i++)add(e[i],-1);
    31     sort(e+l,e+r+1,cmp);
    32 }
    33 int main(){
    34     scanf("%d%d",&n,&m);
    35     for(int i=1;i<=n;i++)scanf("%d",&a[i]),pos[a[i]]=i;
    36     for(int i=1;i<=n;i++){s[a[i]]+=query(a[i]+1,n);add(a[i],1);ans+=s[a[i]];}
    37     memset(c,0,sizeof(c));
    38     for(int i=n;i>=1;i--){s[a[i]]+=sum(a[i]);add(a[i],1);}
    39     memset(c,0,sizeof(c));
    40     for(int i=1;i<=m;i++)scanf("%d",&e[i]),t[i]=e[i];
    41     solve(1,m);
    42     for(int i=1;i<=m;i++){
    43         printf("%lld
    ",ans);
    44         ans-=s[t[i]];
    45     }
    46     return 0;
    47 }
    View Code

     话说这是不是有点压行啊。。。

  • 相关阅读:
    java RSA加密解密
    spring boot 错误处理机制
    Redis 服务常见的几个错误解决方案
    Nginx目录遍历功能时间相差8小时
    翻过大山越过海洋看到了什么
    【分享】分层明确高度定制化的 Python Flask MVC
    编程浪子客服系统开源啦
    快速搭建一个直播Demo
    免费为网站加上HTTPS
    Mac 下安装Fiddler抓包工具
  • 原文地址:https://www.cnblogs.com/2017SSY/p/10199519.html
Copyright © 2011-2022 走看看