主席树 bzoj2653

32 篇文章 0 订阅
10 篇文章 0 订阅

clj的题。。。。

一开始因为下标从1开始记得闹了好长时间。。。后来才看见原来题上说了要从0开始。。。


应该算是比较基础的主席树题目

具体的可以看clj的解题报告。。不过这个报告不算很好找

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAX 2560005

using namespace std;

int child[2][MAX],value[MAX],Lmax[MAX],Rmax[MAX],tree[MAX],n,m,tot=0;

struct wbysr
{
	int num,id;
}a[MAX];

bool cmp(wbysr a1,wbysr a2)
{
	return a1.num<a2.num;
}

void up(int x)
{
	value[x]=value[child[0][x]]+value[child[1][x]];
	Lmax[x]=max(Lmax[child[0][x]],value[child[0][x]]+Lmax[child[1][x]]);//???
	Rmax[x]=max(Rmax[child[1][x]],value[child[1][x]]+Rmax[child[0][x]]);
}

int build(int la,int ra)
{
	int root=tot++;
	if(la==ra)
	{
		value[root]=Lmax[root]=Rmax[root]=1;
		return root;
	}
	int mid=(la+ra)>>1;
	child[0][root]=build(la,mid);
	child[1][root]=build(mid+1,ra);
	up(root);
	return root;
}

int insert(int root,int la,int ra,int pos,int Value)
{
	int New=tot++;
	if(la==ra)
	{
		value[New]=Lmax[New]=Rmax[New]=Value;
		return New;
	}
	int mid=(la+ra)>>1;
	if(pos<=mid)
	{
		child[0][New]=insert(child[0][root],la,mid,pos,Value);
		child[1][New]=child[1][root];
		root=child[0][root];
	}
	else
	{
		child[1][New]=insert(child[1][root],mid+1,ra,pos,Value);
		child[0][New]=child[0][root];
		root=child[1][root];
	}
	up(New);
	return New;
}

int ask_value(int x,int la,int ra,int l,int r)
{
	if(la==l&&ra==r)
		return value[x];
	int mid=(la+ra)>>1;
	if(r<=mid)
		return ask_value(child[0][x],la,mid,l,r);
	else
		if(l>mid)
			return ask_value(child[1][x],mid+1,ra,l,r);
		else
			return ask_value(child[0][x],la,mid,l,mid)+ask_value(child[1][x],mid+1,ra,mid+1,r);
}

int ask_l(int x,int la,int ra,int l,int r)
{
	if(la==l&&ra==r)
		return Lmax[x];
	int mid=(la+ra)>>1;
	if(r<=mid)
		return ask_l(child[0][x],la,mid,l,r);
	else
		if(l>mid)
			return ask_l(child[1][x],mid+1,ra,l,r);
		else
			return max(ask_l(child[0][x],la,mid,l,mid),ask_value(child[0][x],la,mid,l,mid)+ask_l(child[1][x],mid+1,ra,mid+1,r));
}

int ask_r(int x,int la,int ra,int l,int r)
{
	if(la==l&&ra==r)
		return Rmax[x];
	int mid=(la+ra)>>1;
	if(r<=mid)
		return ask_r(child[0][x],la,mid,l,r);
	else
		if(l>mid)
			return ask_r(child[1][x],mid+1,ra,l,r);
		else
			return max(ask_r(child[0][x],la,mid,l,mid)+ask_value(child[1][x],mid+1,ra,mid+1,r),ask_r(child[1][x],mid+1,ra,mid+1,r));
}

bool check(int x,int a1,int b,int c,int d)
{
	int Return=0;
	if(b+1<=c-1)
		Return+=ask_value(tree[x],0,n-1,b+1,c-1);
	Return+=ask_r(tree[x],0,n-1,a1,b);
	Return+=ask_l(tree[x],0,n-1,c,d);
	return Return>=0;
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i].num),a[i].id=i;
	sort(a,a+n,cmp);
	tree[0]=build(0,n-1);
	for(int i=1;i<n;i++)
		tree[i]=insert(tree[i-1],0,n-1,a[i-1].id,-1);
	scanf("%d",&m);

	int ans=0;
	while(m--)
	{
		int ask[5];
		for(int i=1;i<=4;i++)
			scanf("%d",&ask[i]);
		for(int i=1;i<=4;i++)
			ask[i]=(ask[i]+ans)%n;
		sort(ask+1,ask+5);
		int L=0,R=n-1;
		while(L<=R)
		{
			int mid=(L+R)>>1;
			if(check(mid,ask[1],ask[2],ask[3],ask[4]))
				L=mid+1,ans=a[mid].num;
			else
				R=mid-1;
		}
		printf("%d\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值