P3157 [CQOI2011]动态逆序对
Posted fighting-sh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3157 [CQOI2011]动态逆序对相关的知识,希望对你有一定的参考价值。
P3157 [CQOI2011]动态逆序对
https://www.luogu.org/problemnew/show/P3157
题目描述
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
输入输出格式
输入格式:
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
输出格式:
输出包含m行,依次为删除每个元素之前,逆序对的个数。
输入输出样例
说明
N<=100000 M<=50000
树状数组套主席树
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<queue> 10 #define N 100005 11 using namespace std; 12 13 struct sair{ 14 int l,r,sum; 15 }tree[N*150]; 16 int n; 17 int root[N],a[N],b[N],c[N],cnt; 18 void Add(int x){ 19 while(x<=n){ 20 c[x]++; 21 x+= x&(-x); 22 } 23 } 24 25 int getsum(int x){ 26 int sum=0; 27 while(x){ 28 sum+=c[x]; 29 x-= x&(-x); 30 } 31 return sum; 32 } 33 34 void add(int cur,int l,int r,int p,int v){ 35 tree[cur].sum+=v; 36 if(l==r){ 37 return; 38 } 39 int mid=(l+r)/2; 40 if(p<=mid){ 41 if(!tree[cur].l){ 42 tree[cur].l=++cnt; 43 } 44 add(tree[cur].l,l,mid,p,v); 45 } 46 else{ 47 if(!tree[cur].r){ 48 tree[cur].r=++cnt; 49 } 50 add(tree[cur].r,mid+1,r,p,v); 51 } 52 } 53 54 int query(int L,int R,int cur,int l,int r){ 55 if(!cur){ 56 return 0; 57 } 58 if(L<=l&&R>=r){ 59 return tree[cur].sum; 60 } 61 int mid=(l+r)/2; 62 int ans=0; 63 if(L<=mid) ans+=query(L,R,tree[cur].l,l,mid); 64 if(R>mid) ans+=query(L,R,tree[cur].r,mid+1,r); 65 return ans; 66 } 67 68 int main(){ 69 int m,v,p,j; 70 scanf("%d %d",&n,&m); 71 long long ans=0; 72 for(int i=1;i<=n;i++){ 73 scanf("%d",&a[i]); 74 b[a[i]]=i; 75 Add(a[i]); 76 ans+=getsum(n)-getsum(a[i]); 77 for(j=i;j<=n;j+= j&(-j)){ 78 if(!root[j]){ 79 root[j]=++cnt; 80 } 81 add(root[j],1,n,a[i],1); 82 } 83 } 84 for(int i=1;i<=m;i++){ 85 printf("%lld ",ans); 86 scanf("%d",&v); 87 p=b[v]; 88 j=p-1; 89 while(j){ 90 ans-=query(v+1,n,root[j],1,n); 91 j-= j&(-j); 92 } 93 j=n; 94 while(j){ 95 ans-=query(1,v-1,root[j],1,n); 96 j-= j&(-j); 97 } 98 j=p; 99 while(j){ 100 ans+=query(1,v-1,root[j],1,n); 101 j-= j&(-j); 102 } 103 j=p; 104 while(j<=n){ 105 add(root[j],1,n,v,-1); 106 j+= j&(-j); 107 } 108 } 109 }
以上是关于P3157 [CQOI2011]动态逆序对的主要内容,如果未能解决你的问题,请参考以下文章
洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治
[Luogu P3157][CQOI2011]动态逆序对 (树套树)
LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)