BZOJ 3744: Gty的妹子序列

3744: Gty的妹子序列

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

2

HINT

Source

By Autumn

分析:

如果离线就是莫队的板子题...

在线的话我们考虑分块(数据范围这么小不分块对不起出题人...),我们记录$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

posted @ 2017-03-21 16:10  NeighThorn  阅读(200)  评论(0编辑  收藏  举报