BZOJ 3744: Gty的妹子序列 [分块]

时间:2021-09-29 05:02:38

传送门

题意:询问区间内逆序对数


感觉这种题都成套路题了

两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个

f我直接处理成到元素j,方便一点

用个树状数组就行了

预处理和查询都带$log$所以还是开根号n比较科学吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e4+, M=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
} int n, a[N], Q, mp[N], l, r;
struct meow{int l,r;} b[M];
int block, m, pos[N];
inline void ini(){
block=sqrt(n); m=(n-)/block+;
for(int i=;i<=n;i++) pos[i]=(i-)/block+;
for(int i=;i<=m;i++) b[i].l=(i-)*block+, b[i].r=i*block;
b[m].r=n;
}
struct Block{
int c[N];
inline void add(int p,int v) {for(;p<=*mp;p+=(p&-p)) c[p]+=v;}
inline int sum(int p) {int re=; for(;p;p-=(p&-p)) re+=c[p]; return re;}
int f[M][N], s[M][N];
void Set(int x){
for(int i=b[x].l; i<=n; i++)
f[x][i]= f[x][i-]+sum(*mp)-sum(a[i]), add(a[i], );// printf("f %d %d %d\n",x,i,f[x][i]);
memset(c, , sizeof(c)); for(int i=b[x].l; i<=b[x].r; i++) s[x][a[i]]++;
for(int i=; i<=*mp; i++) s[x][i]+= s[x][i-];
for(int i=; i<=*mp; i++) s[x][i]+= s[x-][i];// printf("s %d %d %d\n",x,i,s[x][i]);;
} int Que(int l,int r){
int pl=pos[l], pr=pos[r];
int ans=;
if(pl==pr){
for(int i=l;i<=r;i++) ans+= sum(*mp)-sum(a[i]), add(a[i], );
for(int i=l;i<=r;i++) add(a[i], -);
}else{
ans= f[pl+][r]; //printf("ans %d \n",ans);
for(int i=b[pr].l; i<=r; i++) add(a[i], );
for(int i=b[pl].r; i>=l; i--) ans+= sum(a[i]-) + s[pr-][a[i]-] - s[pl][a[i]-], add(a[i], );
for(int i=b[pr].l; i<=r; i++) add(a[i], -);
for(int i=l; i<=b[pl].r; i++) add(a[i], -);
}
return ans;
}
}B;
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<=n;i++) a[i]=mp[i]=read();
sort(mp+, mp++n); *mp=unique(mp+, mp++n) - mp - ;
for(int i=;i<=n;i++) a[i]=lower_bound(mp+, mp++*mp, a[i]) - mp;
//for(int i=1;i<=n;i++) printf("%d ",a[i]); puts("");
ini();
for(int i=;i<=m;i++) B.Set(i); Q=read(); int lastans=;
while(Q--){
//l=read(), r=read();
l=read()^lastans, r=read()^lastans;
if(l>r) swap(l, r);
lastans=B.Que(l, r); printf("%d\n",lastans);
}
}