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