Description
Autumn终于会求区间逆序对了!Bakser神犇决定再考验一下他,他说道:
“在Gty的妹子序列里,某个妹子的美丽度可也是会变化的呢。你还能求出某个区间中妹子们美丽度的逆序对数吗?当然,为了方便,这次我们规定妹子们的美丽度在[1,n]中。仍然强制在线。”
Autumn需要你的帮助。
给定一个正整数序列a(1<=ai<=n),支持单点修改,对于每次询问,输出al...ar中的逆序对数,强制在线。
Input
第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1...an(1<=ai<=n)。
接下来一行包括一个整数m(1<=m<=50000),表示操作的个数。
接下来m行,每行包括3个整数。
0 L R (1<=L<=R<=n) 询问[L,R]中的逆序对数。
1 p v (1<=p<=n,1<=v<=n) 将p位置的数修改为v。
L,R,p,v 都需要异或上一次的答案,保证异或之后的值是合法的。
保证涉及的所有数在int内。
Output
对每个询问,单独输出一行,表示al...ar中的逆序对数。对每个询问,单独输出一行,表示al...ar中的逆序对数。
Sample Input
10
1 7 5 6 9 4 9 4 4 7
10
0 4 6
0 5 8
0 1 10
1 25 19
0 19 25
1 14 4
0 12 12
0 2 5
1 8 7
1 1 10
1 7 5 6 9 4 9 4 4 7
10
0 4 6
0 5 8
0 1 10
1 25 19
0 19 25
1 14 4
0 12 12
0 2 5
1 8 7
1 1 10
Sample Output
2
3
16
13
0
2
Solution
分块,同时维护几个数组:
$f[i]$表示第$i$块内部的逆序对个数。
$g[i][j]$表示第$i$块和第$j$块能形成的逆序对个数,第二维用树状数组维护。
$s[i][j]$表示前$i$块里$j$数出现的次数,第二维同样用树状数组维护。
查询就利用这三个数组查一下,利用好树状数组前缀和的性质。乱七八糟加加减减。
修改就维护好这三个数组就好了……
速度倒数第二$46s$低空飞过……心情简单……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #define N (50009) 6 #define S (259) 7 using namespace std; 8 9 int n,m,opt,l,r,ans,num,f[S],a[N]; 10 int ID[N],L[S],R[S]; 11 12 inline int read() 13 { 14 int x=0,w=1; char c=getchar(); 15 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 16 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 17 return x*w; 18 } 19 20 struct BIT 21 { 22 int c[N]; 23 void Update(int x,int v) 24 { 25 for (; x<=n; c[x]+=v,x+=(x&-x)); 26 } 27 int Query(int x) 28 { 29 int ans=0; 30 for (; x; ans+=c[x],x-=(x&-x)); 31 return ans; 32 } 33 }B,g[S],s[S]; 34 35 void Build() 36 { 37 int unit=sqrt(n); 38 num=n/unit+(n%unit!=0); 39 for (int i=1; i<=num; ++i) 40 L[i]=(i-1)*unit+1, R[i]=i*unit; 41 R[num]=n; 42 for (int i=1; i<=num; ++i) 43 for (int j=L[i]; j<=R[i]; ++j) ID[j]=i; 44 } 45 46 void Preprocess() 47 { 48 for (int i=1; i<=num; ++i) 49 { 50 for (int j=L[i]; j<=R[i]; ++j) 51 { 52 f[i]+=B.Query(n)-B.Query(a[j]); 53 B.Update(a[j],1); 54 } 55 for (int j=L[i]; j<=R[i]; ++j) B.Update(a[j],-1); 56 } 57 for (int i=2; i<=num; ++i) 58 for (int j=1; j<=i-1; ++j) 59 { 60 for (int k=L[j]; k<=R[j]; ++k) B.Update(a[k],1); 61 for (int k=L[i]; k<=R[i]; ++k) g[i].Update(j,B.Query(n)-B.Query(a[k])); 62 for (int k=L[j]; k<=R[j]; ++k) B.Update(a[k],-1); 63 } 64 for (int i=1; i<=num; ++i) 65 for (int j=L[i]; j<=R[i]; ++j) s[i].Update(a[j],1); 66 for (int i=2; i<=num; ++i) 67 for (int j=1; j<=n; ++j) s[i].Update(j,s[i-1].Query(j)-s[i-1].Query(j-1)); 68 } 69 70 int Calc(int l,int r) 71 { 72 int ans=0; 73 if (ID[l]==ID[r]) 74 { 75 for (int i=l; i<=r; ++i) 76 { 77 ans+=B.Query(n)-B.Query(a[i]); 78 B.Update(a[i],1); 79 } 80 for (int i=l; i<=r; ++i) B.Update(a[i],-1); 81 return ans; 82 } 83 for (int i=l; i<=R[ID[l]]; ++i) 84 { 85 ans+=s[ID[r]-1].Query(a[i]-1)-s[ID[l]].Query(a[i]-1); 86 ans+=B.Query(n)-B.Query(a[i]); 87 B.Update(a[i],1); 88 } 89 for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],-1); 90 91 for (int i=L[ID[r]]; i<=r; ++i) 92 { 93 ans+=(s[ID[r]-1].Query(n)-s[ID[r]-1].Query(a[i]))-(s[ID[l]].Query(n)-s[ID[l]].Query(a[i])); 94 ans+=B.Query(n)-B.Query(a[i]); 95 B.Update(a[i],1); 96 } 97 for (int i=L[ID[r]]; i<=r; ++i) B.Update(a[i],-1); 98 99 for (int i=ID[l]+1; i<=ID[r]-1; ++i) ans+=f[i]; 100 for (int i=ID[l]+2; i<=ID[r]-1; ++i) 101 ans+=g[i].Query(i-1)-g[i].Query(ID[l]); 102 for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],1); 103 for (int i=L[ID[r]]; i<=r; ++i) ans+=B.Query(n)-B.Query(a[i]); 104 for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],-1); 105 return ans; 106 } 107 108 void Change(int x,int k) 109 { 110 int id=ID[x]; 111 for (int i=id; i<=num; ++i) s[i].Update(a[x],-1); 112 for (int i=id; i<=num; ++i) s[i].Update(k,1); 113 114 for (int i=1; i<=id-1; ++i) 115 { 116 g[id].Update(i,-s[i].Query(n)+s[i].Query(a[x])+s[i-1].Query(n)-s[i-1].Query(a[x])); 117 g[id].Update(i,s[i].Query(n)-s[i].Query(k)-s[i-1].Query(n)+s[i-1].Query(k)); 118 } 119 for (int i=id+1; i<=num; ++i) 120 { 121 g[i].Update(id,-s[i].Query(a[x]-1)+s[i-1].Query(a[x]-1)); 122 g[i].Update(id,s[i].Query(k-1)-s[i-1].Query(k-1)); 123 } 124 125 f[id]=0; a[x]=k; 126 for (int i=L[id]; i<=R[id]; ++i) 127 { 128 f[id]+=B.Query(n)-B.Query(a[i]); 129 B.Update(a[i],1); 130 } 131 for (int i=L[id]; i<=R[id]; ++i) B.Update(a[i],-1); 132 } 133 134 int main() 135 { 136 n=read(); 137 Build(); 138 for (int i=1; i<=n; ++i) a[i]=read(); 139 Preprocess(); 140 m=read(); 141 while (m--) 142 { 143 opt=read(); l=read(); r=read(); 144 l^=ans; r^=ans; 145 if (opt==0) printf("%d ",ans=Calc(l,r)); 146 else Change(l,r); 147 } 148 }