Dynamic Inversions
Time Limit: 30000/15000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
SubmitStatus
Problem Description
给出N个数a[1],a[2] ... a[N],有M个操作,每个操作给出x,y两个数,你将a[x],a[y]交换,然后求交换后数组的逆序对个数。
逆序对的意思是1 <= i < j <= N 且a[i] > a[j].
Input
多组数据,每组数据:
一个N,接下来一行有N个数a[1]... a[N]
再下去一行是M,最后M行每行两个数x,y
1 <= N,M <= 10^5, 1 <= x,y <= N,1 <= a[i] <= 50
Output
对于每组数据,输出M + 1行,第一行是开始时的逆序对数目,接下去M行每行一个数,表示这次修改后的逆序对数目
Sample Input
2 1 2 1 2 1 3 1 2 3 3 1 2 2 3 3 1
Sample Output
0 1 0 1 2 1
Hint
第二个样例,一开始1 2 3,逆序对数为0,交换第1,2个元素,变为2 1 3,答案为1,交换第2和3个元素,变为2 3 1,逆序对数为2,交换第3和1个元素,逆序对数为1,此时序列变成1 3 2
二维树状数组做法:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 #include <algorithm> 6 using namespace std; 7 #define ll long long 8 int b[60][100100],a[100100],n,c[60]; 9 int lowbit(int x) 10 { 11 return x&(-x); 12 } 13 void update1(int x) 14 { 15 while(x<60) 16 { 17 c[x]++; 18 x+=lowbit(x); 19 } 20 } 21 int query1(int x) 22 { 23 int sum=0; 24 while(x>0) 25 { 26 sum+=c[x]; 27 x-=lowbit(x); 28 } 29 return sum; 30 } 31 void update(int x,int y,int z) 32 { 33 for(int i=x; i<=50; i+=lowbit(i)) 34 for(int j=y; j<=n; j+=lowbit(j)) 35 b[i][j]+=z; 36 } 37 int query(int x,int y,int x1,int y1) 38 { 39 int ans=0,i,j; 40 for(i=y;i>0;i-=lowbit(i)) 41 for(j=y1;j>0;j-=lowbit(j)) 42 ans+=b[i][j]; 43 44 for(i=x-1;i>0;i-=lowbit(i)) 45 for(j=y1;j>0;j-=lowbit(j)) 46 ans-=b[i][j]; 47 48 for(i=y;i>0;i-=lowbit(i)) 49 for(j=x1-1;j>0;j-=lowbit(j)) 50 ans-=b[i][j]; 51 52 for(i=x-1;i>0;i-=lowbit(i)) 53 for(j=x1-1;j>0;j-=lowbit(j)) 54 ans+=b[i][j]; 55 return ans; 56 } 57 int main() 58 { 59 int i,m,x,y; 60 ll ans; 61 while(~scanf("%d",&n)) 62 { 63 ans=0; 64 memset(b,0,sizeof(b)); 65 memset(c,0,sizeof(c)); 66 for(i=1; i<=n; i++) 67 { 68 scanf("%d",&a[i]); 69 update1(a[i]); 70 ans+=i-query1(a[i]); 71 update(a[i],i,1); 72 } 73 printf("%lld\n",ans); 74 scanf("%d",&m); 75 for(i=0; i<m; i++) 76 { 77 scanf("%d%d",&x,&y); 78 if(x>y)swap(x,y); 79 ans-=query(a[y]+1,50,x+1,y); 80 ans+=query(1,a[y]-1,x+1,y); 81 ans+=query(a[x]+1,50,x,y-1); 82 ans-=query(1,a[x]-1,x,y-1); 83 if(a[x]>a[y])ans--; 84 else if(a[x]<a[y])ans++; 85 update(a[x],x,-1); 86 update(a[x],y,1); 87 update(a[y],y,-1); 88 update(a[y],x,1); 89 swap(a[x],a[y]); 90 printf("%lld\n",ans); 91 } 92 } 93 }
50个一维的做法:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 #include <algorithm> 6 using namespace std; 7 #define ll long long 8 int a[51][100010],b[60],n,c[60]; 9 int lowbit(int x) 10 { 11 return x&(-x); 12 } 13 int update(int x) 14 { 15 while(x<60) 16 { 17 b[x]++; 18 x+=lowbit(x); 19 } 20 } 21 int update1(int i,int x,int y) 22 { 23 while(x<=n) 24 { 25 a[i][x]+=y; 26 x+=lowbit(x); 27 } 28 } 29 int query(int x) 30 { 31 int sum=0; 32 while(x>0) 33 { 34 sum+=b[x]; 35 x-=lowbit(x); 36 } 37 return sum; 38 } 39 int query1(int i,int x) 40 { 41 int sum=0; 42 while(x>0) 43 { 44 sum+=a[i][x]; 45 x-=lowbit(x); 46 } 47 return sum; 48 } 49 int main() 50 { 51 int i,j,m,x,y,z; 52 ll ans,temp,temp1; 53 while(~scanf("%d",&n)) 54 { 55 memset(b,0,sizeof(b)); 56 memset(a,0,sizeof(a)); 57 memset(c,0,sizeof(c)); 58 ans=0; 59 for(i=1; i<=n; i++) 60 { 61 scanf("%d",&a[0][i]); 62 c[a[0][i]]++; 63 ans+=i-query(a[0][i])-1; 64 update(a[0][i]); 65 update1(a[0][i],i,1); 66 } 67 printf("%lld\n",ans); 68 scanf("%d",&m); 69 for(i=0; i<m; i++) 70 { 71 scanf("%d%d",&x,&y); 72 if(x>y)swap(x,y); 73 z=y-x; 74 temp=0; 75 for(j=1; j<a[0][y]; j++) 76 { 77 temp+=query1(j,y-1)-query1(j,x-1); 78 } 79 temp1=query1(j,y-1)-query1(j,x-1); 80 ans+=temp-(z-temp1-temp); 81 temp=0; 82 for(j=1; j<a[0][x]; j++) 83 { 84 temp+=query1(j,y-1)-query1(j,x-1); 85 } 86 temp1=query1(j,y-1)-query1(j,x-1); 87 ans+=(z-temp1-temp)-temp; 88 update1(a[0][x],x,-1); 89 update1(a[0][x],y,1); 90 update1(a[0][y],y,-1); 91 update1(a[0][y],x,1); 92 swap(a[0][y],a[0][x]); 93 printf("%lld\n",ans); 94 } 95 } 96 }
Dynamic Inversions 50个树状数组
时间: 2024-10-13 05:35:23