Bzoj 2653
Bzoj 1951

Bzoj 3110

coc youyl posted @ 2015年6月27日 20:02 in bzoj , 457 阅读

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3110

题目分类:数据结构,树套树

题意:

修改操作每次给一个位置加入k个权值为c的数

询问操作每次询问一个区间内的k大数

题解:

使用树套树的方法维护。

外面一圈用线段树表示数的权值。

里面一圈用线段树维护区间内的数。

二分的时候直接在线段树上二分省去一个log

程序:

#include<cstdio>
using namespace std;
struct node
{
	int lson,rson,lazy,summ;
}a[33000000];
int root[500000],siz,n;
inline void build(int x,int le,int ri)
{
	root[x]=++siz;
	if(le==ri)return;
	build((x<<1),le,(le+ri)/2);
	build((x<<1)+1,(le+ri)/2+1,ri);
}
inline void pushdown(int x,int l,int mi,int r)
{
	int le=a[x].lson,ri=a[x].rson;
	if(le==0)siz++,a[x].lson=siz,le=siz;
	a[le].lazy+=a[x].lazy;a[le].summ+=a[x].lazy*(mi-l+1);
	if(ri==0)siz++,a[x].rson=siz,ri=siz;
	a[ri].summ+=a[x].lazy*(r-mi);a[ri].lazy+=a[x].lazy;
	a[x].lazy=0;
}
inline void update(int x)
{
	a[x].summ=a[a[x].lson].summ+a[a[x].rson].summ;
}
inline int query(int x,int le,int ri,int lec,int ric)
{
//	if(le==1&&ri==(n<<1)+1)printf("qu2:%d %d %d %d %d %d\n",x,le,ri,lec,ric,a[x].summ);
	if(x==0)return 0;
	if(lec<=le&&ric>=ri)return a[x].summ;
	pushdown(x,le,(le+ri)/2,ri);
	int ss=0;
	if(lec<=(le+ri)/2)ss+=query(a[x].lson,le,(le+ri)/2,lec,ric);
	if(ric>=(le+ri)/2+1)ss+=query(a[x].rson,(le+ri)/2+1,ri,lec,ric);
	return ss;
}
inline int edit(int x,int le,int ri,int lec,int ric)
{
	if(x==0)siz++,x=siz;
//	printf("%d %d %d %d %d\n",x,le,ri,lec,ric);
	if(lec<=le&&ric>=ri){a[x].summ+=(ri-le+1);a[x].lazy++;return x;}
	pushdown(x,le,(le+ri)/2,ri);
//	if(lec<=le&&ric>=ri){a[x].summ++;a[x].lazy++;return x;}
	if(lec<=(le+ri)/2)a[x].lson=edit(a[x].lson,le,(le+ri)/2,lec,ric);
	if(ric>=(le+ri)/2+1)a[x].rson=edit(a[x].rson,(le+ri)/2+1,ri,lec,ric);
	update(x);
	return x;
}
inline void edit(int x,int va,int le,int ri,int lec,int ric)
{
//	printf("edit:%d %d %d %d %d %d\n",x,va,le,ri,lec,ric);
	root[x]=edit(root[x],1,(n<<1)+1,lec,ric);
	if(le==ri){return;}
	if(va<=(le+ri)/2)edit((x<<1),va,le,(le+ri)/2,lec,ric);
	else edit((x<<1)+1,va,(le+ri)/2+1,ri,lec,ric);
}
inline int query(int x,int le,int ri,int va,int lec,int ric)
{
//	printf("%d %d %d %d %d %d\n",x,le,ri,va,lec,ric);
	if(le==ri)return le;
	int tmp=query(root[(x<<1)],1,(n<<1)+1,lec,ric);//printf("%d\n",tmp);
	if(tmp<va)return query((x<<1)+1,(le+ri)/2+1,ri,va-tmp,lec,ric);
	return query((x<<1),le,(le+ri)/2,va,lec,ric);
}
int m,x1,x2,x3,x4;
int main()
{
	//freopen("sequence.in","r",stdin);
	//freopen("sequence.out","w",stdout);
	scanf("%d %d",&n,&m);
	build(1,1,(n<<1)+1);
	for (int i=1;i<=m;i++)
	{
		scanf("%d %d %d %d",&x1,&x2,&x3,&x4);
		if(x1==1)
		{
			x4=(n+1)-x4;
			edit(1,x4,1,(n<<1)+1,x2,x3);
		}
		else
		{
			printf("%d\n",n+1-query(1,1,(n<<1)+1,x4,x2,x3));
		}
	}//printf("%d\n",siz);
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter