【BZOJ3289】Mato的文件管理 莫队+树状数组
题目大意:给定一个长度为 N 的序列,M 个询问,每次询问区间逆序对的个数。
题解:用树状数组加速答案转移。
代码如下
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=5e4+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll fpow(ll a,ll b,ll c){ll ret=1%c;for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;return ret;}
inline ll read(){
ll x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
}
/*------------------------------------------------------------*/
int n,m,bsize,a[maxn],d[maxn],tot;
struct query{int id,bl,l,r;}q[maxn];
bool cmp(const query &x,const query &y){return x.bl!=y.bl?x.bl<y.bl:(x.bl&1)?x.r<y.r:x.r>y.r;}
inline int get(int x){return (x-1)/bsize+1;}
ll bit[maxn],now,l=1,r=0,ans[maxn];
void modify(int pos,ll val){
for(int i=pos;i<=n;i+=i&-i)bit[i]+=val;
}
ll query(int pos){
ll ret=0;
for(int i=pos;i;i-=i&-i)ret+=bit[i];
return ret;
}
void read_and_parse(){
n=read(),bsize=sqrt(n);
for(int i=1;i<=n;i++)a[i]=d[i]=read();
sort(d+1,d+n+1);
tot=unique(d+1,d+n+1)-d-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(d+1,d+tot+1,a[i])-d;
m=read();
for(int i=1;i<=m;i++){
q[i].id=i,q[i].l=read(),q[i].r=read();
q[i].bl=get(q[i].l);
}
sort(q+1,q+m+1,cmp);
}
inline void update(int pos,int f){
if(f==0){// r +
now+=query(n)-query(a[pos]);
modify(a[pos],1);
}
else if(f==1){// r -
now-=query(n)-query(a[pos]);
modify(a[pos],-1);
}
else if(f==2){// l -
now+=query(a[pos]-1);
modify(a[pos],1);
}
else{
now-=query(a[pos]-1);
modify(a[pos],-1);
}
}
void solve(){
for(int i=1;i<=m;i++){
while(r>q[i].r)update(r--,1);
while(r<q[i].r)update(++r,0);
while(l>q[i].l)update(--l,2);
while(l<q[i].l)update(l++,3);
ans[q[i].id]=now;
}
for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
}
int main(){
read_and_parse();
solve();
return 0;
}