bzoj3110 K大数查询 整体二分&树状数组

       本来想用树状数组套树状数组去做的。然后发现树状数组还要动态开点。。就放弃了。然后扒了扒题解发现有整体二分啊。就自己脑补了一下。

       首先,由于数有负的,但是绝对值<=N,于是我们可以用N减去这个数再+1,就变成了(1...2N+1)范围内的数了,然后求第k大的就变成第k小的了,最后只需要输出的时候再减回来即可。

       然后用一个状态(l,r,{S}),表示查询的答案在(l,r)中,或者修改的数的大小在(l,r)中的操作的集合为{S}。那么令mid=(l+r)/2,然后就可以通过只执行修改的数在(l,mid)中的修改操作,来判断询问的答案是否在(l,mid)中了。于是可以递归调用(l,mid,{S1})(mid+1,r,{S2})。最后当l=r时显然此时(l,r,{S})中所有询问的答案为l。

       说的好乱不懂看代码。。。。

AC代码如下:

#include<iostream>
#include<cstdio>
#define ll long long
#define N 100005
using namespace std;

int n,m,tot,ans[N]; ll c[2][N]; bool bo[N]; struct node{ int k,x,y,z,id; }a[N],b[N];
void ins(int k,int x,int t){
	for (; x<=tot; x+=x&-x) c[k][x]+=t;
}
ll getsum(int k,int x){
	ll t=0; for (; x; x-=x&-x) t+=c[k][x]; return t;
}
void mdy(int x,int y,int z){
	ins(0,x,z); ins(1,x,z*(x-1)); ins(0,y+1,-z); ins(1,y+1,-z*y);
}
ll qry(int x,int y){
	return getsum(0,y)*y-getsum(1,y)-getsum(0,x-1)*(x-1)+getsum(1,x-1);
}
int read(){
	int x=0,fu=1; char ch=getchar();
	while (ch<'0' || ch>'9'){ if (ch=='-') fu=-1; ch=getchar(); }
	while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
	return x*fu;
}
void solve(int x,int y,int l,int r){
	int i,j=x,k=x,mid=(l+r)>>1;
	if (l==r){
		for (i=x; i<=y; i++) if (a[i].k) ans[a[i].id]=l;
		return;
	}
	for (i=x; i<=y; i++)
		if (a[i].k){
			ll tmp=qry(a[i].x,a[i].y);
			if (tmp<a[i].z){ bo[i]=0; a[i].z-=(int)tmp; }
			else{ bo[i]=1; k++; }
		}else if (a[i].z<=mid){ mdy(a[i].x,a[i].y,1); bo[i]=1; k++; }
				else bo[i]=0;
	for (i=x; i<=y; i++)
		if (!a[i].k && a[i].z<=mid) mdy(a[i].x,a[i].y,-1);
	for (i=x; i<=y; i++)
		if (bo[i]) b[j++]=a[i]; else b[k++]=a[i];
	for (i=x; i<=y; i++) a[i]=b[i];
	solve(x,j-1,l,mid); solve(j,y,mid+1,r);
}
int main(){
	n=read(); m=read(); int i,cnt=0;
	for (i=1; i<=m; i++){
		a[i].k=read()-1; a[i].x=read(); a[i].y=read(); a[i].z=read();
		if (a[i].k) a[i].id=++cnt; else{
			a[i].z=n-a[i].z+1; tot=max(tot,a[i].z);
		}
	}
	solve(1,m,1,tot);
	for (i=1; i<=cnt; i++) printf("%d\n",n-ans[i]+1);
	return 0;
}


by lych

2016.3.10

你可能感兴趣的:(分治,树状数组,整体二分)