BZOJ 3744: Gty的妹子序列
3744: Gty的妹子序列
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1483 Solved: 425
[Submit][Status][Discuss]
Description
我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现
她们排成了一个序列,每个妹子有一个美丽度。
Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间
[l,r]中妹子们美丽度的逆序对数吗?"
蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线。"
请你帮助一下Autumn吧。
给定一个正整数序列a,对于每次询问,输出al...ar中的逆序对数,强制在线。
Input
第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1...an(ai>0,保证ai在int内)。
接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al...ar中的逆序
对数(若ai>aj且i<j,则为一个逆序对)。
l,r要分别异或上一次询问的答案(lastans),最开始时lastans=0。
保证涉及的所有数在int内。
Output
对每个询问,单独输出一行,表示al...ar中的逆序对数。
Sample Input
4
1 4 2 3
1
2 4
1 4 2 3
1
2 4
Sample Output
2
HINT
Source
分析:
如果离线就是莫队的板子题...
在线的话我们考虑分块(数据范围这么小不分块对不起出题人...),我们记录$f[i][j]$代表第$i$的开头位置到第$j$个位置的逆序对数,这个可以树状数组预处理出来...
然后如果询问$lr$在一个块中的话,我们就暴力树状数组查询,否则就找到$l$后面的最靠前的块$i$,然后取出$f[i][r]$,对于前面的数字我们查询区间中这个数字后面的比它小的数的个数...这个可以主席数维护...
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
//by NeighThorn
using namespace std;
const int maxn=50000+5,maxblock=233+5,maxm=7000000+5;
int n,m,ans,blo,tot,lala,a[maxn],f[maxblock][maxn],id[maxn],be[maxn],mp[maxn],tr[maxn],ls[maxm],rs[maxm],sum[maxm],root[maxn];
inline void insert(int x,int y){
for(;x<=tot;x+=x&-x)
tr[x]+=y;
}
inline int query(int x){
int res=0;
for(;x;x-=x&-x)
res+=tr[x];
return res;
}
inline void change(int l,int r,int x,int &y,int pos){
y=++lala;sum[y]=sum[x]+1;
if(l==r) return;
int mid=(l+r)>>1;ls[y]=ls[x];rs[y]=rs[x];
if(pos<=mid)
change(l,mid,ls[x],ls[y],pos);
else
change(mid+1,r,rs[x],rs[y],pos);
}
inline int query(int l,int r,int x,int y,int L,int R){
// cout<<l<<" "<<r<<" "<<x<<" "<<y<<" "<<L<<" "<<R<<endl;
if(l==L&&r==R)
return sum[y]-sum[x];
int mid=(l+r)>>1;
if(R<=mid)
return query(l,mid,ls[x],ls[y],L,R);
else if(L>mid)
return query(mid+1,r,rs[x],rs[y],L,R);
else
return query(l,mid,ls[x],ls[y],L,mid)+query(mid+1,r,rs[x],rs[y],mid+1,R);
}
signed main(void){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d",&n);blo=sqrt(n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),id[i]=(i-1)/blo+1;
memcpy(mp,a,sizeof(mp));sort(mp+1,mp+n+1);tot=unique(mp+1,mp+n+1)-mp-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+tot+1,a[i])-mp;
for(int i=1;i<=id[n];i++) be[i]=lower_bound(id+1,id+n+1,i)-id;
for(int i=1;i<=id[n];i++){
for(int j=be[i];j<=n;j++)
insert(a[j],1),f[i][j]=f[i][j-1]+query(tot)-query(a[j]);
for(int j=be[i];j<=n;j++)
insert(a[j],-1);
}
for(int i=1;i<=n;i++)
change(1,tot,root[i-1],root[i],a[i]);
scanf("%d",&m);ans=0;
for(int q=1,l,r;q<=m;q++){
scanf("%d%d",&l,&r);l^=ans,r^=ans;ans=0;
if(id[l]==id[r]){
for(int i=l;i<=r;i++)
insert(a[i],1),ans+=query(tot)-query(a[i]);
for(int i=l;i<=r;i++)
insert(a[i],-1);
}
else{
int x=upper_bound(be+1,be+id[n]+1,l)-be;
ans=f[x][r];
for(int i=l;i<be[x];i++)
if(a[i]!=1) ans+=query(1,tot,root[i],root[r],1,a[i]-1);
}
printf("%d\n",ans);
}
return 0;
}
By NeighThorn

浙公网安备 33010602011771号