zoukankan      html  css  js  c++  java
  • luogu P3157 [CQOI2011]动态逆序对(CDQ分治)

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    题解

    我们发现一个数的贡献,就是就是t'<t(删除时间),xb'<xb(下标),w'>w(权值)的数的数量和t'>t,xb'>xb,w'<w的数的数量之和。

    这就是一个三维偏序类型的题,所以做两遍CDQ分治分别的到这两种贡献。最后用总逆序对数减去就好了。

    1A真开心。。。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cmath>
      6 using namespace std;
      7 const long long N=100100;
      8 long long n,m,a[N],b[N],tmp,tr[N],ans[N],book[N],ma[N],tot;
      9 struct query{
     10     long long id,xb,w;
     11 }q[N],c[N];
     12 bool cmp(query a,query b){
     13     return a.id>b.id;
     14 }
     15 void gb(long long l,long long r){
     16     if(l==r)return;
     17     long long mid=(l+r)>>1;
     18     gb(l,mid);
     19     gb(mid+1,r);
     20     long long ll=l;
     21     long long lr=mid+1;
     22     long long cnt=0;
     23     while(ll<=mid&&lr<=r){
     24         cnt++;
     25         if(a[ll]<a[lr]){
     26             b[cnt]=a[ll++];
     27         }
     28         else{
     29             b[cnt]=a[lr++];
     30             tmp+=mid-ll+1;
     31         }
     32     }
     33     while(ll<=mid)b[++cnt]=a[ll++];
     34     while(lr<=r)b[++cnt]=a[lr++];
     35     for(long long i=l;i<=r;i++){
     36         a[i]=b[i-l+1];
     37     }
     38 }
     39 long long lowbit(long long x){
     40     return x&-x;
     41 }
     42 void add(long long x,long long w){
     43     for(long long i=x;i<=n;i+=lowbit(i)){
     44         tr[i]+=w;
     45     }
     46 }
     47 long long getsum(long long x){
     48     long long ans=0;
     49     for(long long i=x;i>=1;i-=lowbit(i)){
     50         ans+=tr[i];
     51     }
     52     return ans;
     53 }
     54 void cdq(long long l,long long r){
     55     if(l==r)return;
     56     long long mid=(l+r)>>1;
     57     cdq(l,mid);cdq(mid+1,r);
     58     long long ll=l;long long rl=mid+1;long long now=0;
     59     while(ll<=mid&&rl<=r){
     60         if(q[ll].xb<q[rl].xb){
     61             add(q[ll].w,1);
     62             c[++now]=q[ll++];
     63         }
     64         else{
     65             ans[q[rl].id]+=getsum(n)-getsum(q[rl].w);
     66             c[++now]=q[rl++];
     67         }
     68     }
     69     while(ll<=mid){
     70         add(q[ll].w,1);
     71         c[++now]=q[ll++];
     72     }
     73     while(rl<=r){
     74         ans[q[rl].id]+=getsum(n)-getsum(q[rl].w);
     75         c[++now]=q[rl++];
     76     }
     77     for(long long i=l;i<=mid;i++)add(q[i].w,-1);    
     78     for(long long i=l;i<=r;i++)q[i]=c[i-l+1];
     79 }
     80 void CDQ(long long l,long long r){
     81     if(l==r)return;
     82     long long mid=(l+r)>>1;
     83     CDQ(l,mid);CDQ(mid+1,r);
     84     long long ll=l;long long rl=mid+1;long long now=0;
     85     while(ll<=mid&&rl<=r){
     86         if(q[ll].xb>q[rl].xb){
     87             add(q[ll].w,1);
     88             c[++now]=q[ll++];
     89         }
     90         else{
     91             ans[q[rl].id]+=getsum(q[rl].w);
     92             c[++now]=q[rl++];
     93         }
     94     }
     95     while(ll<=mid){
     96         add(q[ll].w,1);
     97         c[++now]=q[ll++];
     98     }
     99     while(rl<=r){
    100         ans[q[rl].id]+=getsum(q[rl].w);
    101         c[++now]=q[rl++];
    102     }
    103     for(long long i=l;i<=mid;i++)add(q[i].w,-1);
    104     for(long long i=l;i<=r;i++)q[i]=c[i-l+1];
    105 }
    106 int main(){
    107     scanf("%lld%lld",&n,&m);
    108     for(long long i=1;i<=n;i++){
    109         scanf("%lld",&a[i]);
    110         ma[a[i]]=i;
    111     }
    112     for(long long i=1;i<=m;i++){
    113         long long x;
    114         scanf("%lld",&x);
    115         q[i].id=i;q[i].xb=ma[x];q[i].w=x;
    116         book[ma[x]]=1;
    117     }
    118     tot=m;
    119     for(long long i=1;i<=n;i++){
    120         if(book[i]==0){
    121             q[++tot].id=m+1;q[tot].xb=i;q[tot].w=a[i];
    122         }
    123     }
    124     sort(q+1,q+n+1,cmp);
    125     cdq(1,n);
    126     sort(q+1,q+n+1,cmp);
    127     CDQ(1,n);
    128     gb(1,n);
    129     for(long long i=1;i<=m;i++){
    130         printf("%lld
    ",tmp);
    131         tmp-=ans[i];
    132     }
    133     return 0;
    134 }
  • 相关阅读:
    String&StringBuffer&StringBuilder区别
    linux启动流程简介
    nginx视频直播/点播服务干货分享
    Http协议的认识
    php中对象是引用类型吗?
    nginx与php-fpm 504 Gateway Time-out 排查与解决案例
    php header函数常见用途
    php魔术方法
    ajax 和jsonp 不是一码事 细读详解
    php session redis 配置
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9460134.html
Copyright © 2011-2022 走看看