首页 > 代码库 > Dynamic Inversions 50个树状数组
Dynamic Inversions 50个树状数组
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].
逆序对的意思是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
21 212 131 2 331 22 33 1
Sample Output
010121
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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。