BZOJ 3744: Gty的妹子序列(分块)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88672712

题目
求出块内的,跨块的,最后还有散对散的。
全部都可以 O ( n n ) O(n\sqrt n)
具体看代码吧,无力.jpg
为啥分块最后一块的大小不是S啊。
调了3h。

AC Code:

#include<bits/stdc++.h>
#define maxn 50005
#define S 250
using namespace std;

int n,a[maxn],sb[maxn],sa[maxn];
int ans1[S+5][S+5][S+5],bl[maxn];//in block
int ans2[S+5][maxn];//block to pt!s!
int cnt1[maxn];//while
int cnt2[S+5][S+5];//in block
int sbl[S+5],ebl[S+5];
inline bool cmp(const int &u,const int &v){ return a[u]==a[v]?u<v:a[u]<a[v]; }

int merge(int l1,int r1,int l2,int r2){
	static int A[S+5] , B[S+5] , len1 , len2;
	len1 = len2 = 0;
	for(int i=sbl[bl[r1]];i<=r1;i++) if(sa[i]>=l1) A[len1++]=sa[i];
	for(int i=l2;i<=ebl[bl[l2]];i++) if(sa[i]<=r2) B[len2++]=sa[i];
	int i=0,j=0,ret=0;
	for(;i<len1 && j<len2;)
		if(a[A[i]] <= a[B[j]]) i++;
		else ret+=len1-i , j++;
	return ret;
}

int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&a[i]),sb[++sb[0]]=a[i];
	sort(sb+1,sb+1+sb[0]);
	sb[0] = unique(sb+1,sb+1+sb[0])-sb-1;
	for(int i=0;i<n;i++) a[i]=lower_bound(sb+1,sb+1+sb[0],a[i])-sb,bl[i]=i/S,sa[i]=i;
	int m = bl[n-1];
	for(int i=0;i<=m;i++){
		memset(cnt1,0,sizeof cnt1);
		int st = i * S , ed = min(n-1,st + S - 1);
		for(int j=st;j<=ed;j++) cnt1[a[j]]++;
		for(int j=1;j<=sb[0];j++) cnt1[j]+=cnt1[j-1];
		for(int j=st-1;j>=0;j--) ans2[i][j] = ans2[i][j+1] + cnt1[a[j]-1];
		for(int j=sb[0];j>=1;j--) cnt1[j]=cnt1[j]-cnt1[j-1]+cnt1[j+1];
		for(int j=ed+1;j<n;j++) ans2[i][j] = ans2[i][j-1] + cnt1[a[j]+1];
			
		memset(cnt2,0,sizeof cnt2);
		for(int j=0;j+st<=ed;j++)
			for(int k=0;k<j;k++)
				cnt2[j][k] = (k?cnt2[j][k-1]:0) + (a[j+st]<a[k+st]);
		for(int k=0;k+st<=ed;k++)
			for(int j=k;j+st<=ed;j++)
				ans1[i][k][j] = (j?ans1[i][k][j-1]:0) + (j?cnt2[j][j-1]:0) - (k?cnt2[j][k-1]:0);
		sort(sa+st,sa+ed+1,cmp);
		sbl[i] = st , ebl[i] = ed;
	}
	
	int q,la=0;
	scanf("%d",&q);
	for(int u,v;q--;){
		scanf("%d%d",&u,&v);
		u^=la,v^=la;
		u--,v--;
		if(bl[u] == bl[v]) la = ans1[bl[u]][u-sbl[bl[u]]][v-sbl[bl[u]]];
		else{
			la = ans1[bl[u]][u-sbl[bl[u]]][ebl[bl[u]]-sbl[bl[u]]] + ans1[bl[v]][0][v-sbl[bl[v]]];
			for(int i=bl[u]+1;i<=bl[v]-1;i++){
				la += ans1[i][0][ebl[i]-sbl[i]]
				+ ans2[i][u] 
				+ ans2[i][v] - ans2[i][ebl[bl[v]-1]];
			}
			la += merge(u,ebl[bl[u]],sbl[bl[v]],v);
		}
		printf("%d\n",la);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88672712