首页 > 代码库 > bzoj3110: [Zjoi2013]K大数查询

bzoj3110: [Zjoi2013]K大数查询

喜闻乐见的简单树套树= =第一维按权值建树状数组,第二维按下标建动态开点线段树,修改相当于第二维区间加,查询在树状数组上二分,比一般的线段树还短= =可惜并不能跑过整体二分= =另外bzoj上的数据有负数= =额其他树套树方法也是可以的爱怎么套怎么套= =

#include<cstdio>#define J (i+j>>1)#define I (J+1)typedef unsigned ll;const int N=1e5+5;ll n,m,q,i,j,k,l,s,t,v;struct node{	ll s,t;	node *i,*j;};node f[N*320],*e[N];node* back=f;void vary(node*& k,int s,int t,int i=1,int j=n){	if(!k)k=back++;	k->s+=t-s+1;	if(s==i&&t==j)++k->t;	else if(t<I)		vary(k->i,s,t,i,J);	else if(s>J)		vary(k->j,s,t,I,j);	else{		vary(k->i,s,J,i,J);		vary(k->j,I,t,I,j);	}}void eval(node* k,int s,int t,int i=1,int j=n){	if(!k)return;	if(s==i&&t==j){		l+=k->s;return;	}	l+=k->t*(t-s+1);	if(t<I)		eval(k->i,s,t,i,J);	else if(s>J)		eval(k->j,s,t,I,j);	else{		eval(k->i,s,J,i,J);		eval(k->j,I,t,I,j);	}}int main(){	struct{		operator int(){			int x;			scanf("%d",&x);			return x;		}	}it;	n=it,m=n<<1^1,q=it;	while(q--){		j=it,s=it,t=it,k=it;		if(j==2){			for(i=65536,v=j=0;i;i>>=1)				if(j+i<=m){					l=0,eval(e[j+i],s,t);					if(v+l<k)j+=i,v+=l;				}			printf("%d\n",n-j);		}else			for(i=n-k+1;i<=m;i+=i&-i)				vary(e[i],s,t);	}}

  

bzoj3110: [Zjoi2013]K大数查询