• BZOJ3295 动态逆序对


    【问题描述】

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

    【输入格式】

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

    【输出格式】

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

    【输入样例】

    5 4
    1
    5
    3
    4
    2 5 1
    4
    2

    【输出样例】

    5
    2
    2
    1

    【样例解释】

    (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。


    【数据规模】
    N<=100000 , M<=50000

    正解:cdq分治

    解题报告:这个题是让我们边修改边求逆序对,我们可以先离线处理,把删除改成插入,然后序列中所有的逆序对应该满足三个条件,我们用三个字母表示,t表示插入时间,x表示位置,y表示值,然后每一对逆序对应该是t【j】<t【i】,(x【j】<x【i】&& y【j】>y【i】) 或 (x【j】>x【i】 && y【j】<y【i】),然后就转化为经典的三维偏序,用cdq分治解决。

     1 #include <iostream>
     2 #include <iomanip>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <string>
     8 #include <cstring>
     9 #define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    10 #define RG register
    11 #define ll long long
    12 const int N = 105000;
    13 
    14 using namespace std;
    15 
    16 int gi(){
    17     char ch=getchar();int x=0;
    18     while(ch<'0' || ch>'9')ch=getchar();
    19     while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
    20     return x;
    21 }
    22 
    23 struct date{
    24     int x,s;
    25 }d[N],a[N],b[N];
    26 
    27 int f[N],q[N],id[N],y[N],n,m,ans[N];
    28 bool vis[N];
    29 void update(int x,int s){while(x<=n){y[x]+=s;x+=x&(-x);}return;}
    30 int query(int x){int s=0;while(x){s+=y[x];x-=x&(-x);}return s;}
    31 
    32 void cdq(int l,int r){
    33     if (l>=r) return;
    34     RG int i,j,k;
    35     int mid=(l+r)>>1;
    36     cdq(l,mid);
    37     cdq(mid+1,r);
    38     for (i=mid+1,j=l; i<=r; i++){
    39         while(d[j].x<d[i].x && j<=mid) update(d[j].s,1),j++;
    40         ans[d[i].x]+=query(n)-query(d[i].s);
    41     }
    42     for (i=l; i<j; i++) update(d[i].s,-1);
    43     for (i=r,j=mid; i>mid; i--){
    44         while(j>=l && d[j].x>d[i].x) update(d[j].s,1),j--;
    45         ans[d[i].x]+=query(d[i].s);
    46     }
    47     for (i=mid; i>j; i--) update(d[i].s,-1);
    48     int a1=0,b1=0;
    49     for (i=l; i<=mid; i++) a[++a1]=d[i];
    50     for (i=mid+1; i<=r; i++) b[++b1]=d[i];
    51     i=1,j=1,k=l;
    52     while(i<=a1 && j<=b1) if (a[i].x<b[j].x) d[k++]=a[i++];
    53         else d[k++]=b[j++];
    54     while(i<=a1) d[k++]=a[i++];
    55     while(j<=b1) d[k++]=b[j++];
    56     return;
    57 }
    58 
    59 int main(){
    60     File("3295");
    61     n=gi(),m=gi();RG int i,t=1;
    62     for (i=1; i<=n; i++) f[i]=gi(),id[f[i]]=i;
    63     for (i=1; i<=m; i++) q[i]=gi(),vis[q[i]]=1;
    64     for (i=1; i<=n; i++) if (!vis[f[i]]) d[t++]=(date){i,f[i]};
    65     for (i=m; i>=1; i--) d[t++]=(date){id[q[i]],q[i]};
    66     cdq(1,n);
    67     ll sum=0;
    68     for (i=1; i<=n; i++) sum+=ans[i];
    69     for (i=1; i<=m; i++) printf("%lld
    ",sum),sum-=ans[id[q[i]]];
    70     return 0;
    71 }
  • 相关阅读:
    JavaScript 操作 Cookie
    Java监控文件夹变化
    Cookie与Session的区别
    常用插件
    Plugin 'org.springframework.boot:springbootmavenplugin:' not found
    mysql安装(windows)
    idea 安装社区版
    linux安装tomcat
    将克隆的项目上传到自己的github
    tomcat安装配置
  • 原文地址:https://www.cnblogs.com/cjk2001/p/6378040.html
Copyright © 2020-2023  润新知