hdu 6356 Glad You Came 线段树解法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ccsu_cat/article/details/81478220

多校五第七题,昨天由于太贪心(不要和我提贪心,暴力万岁),被第二题卡了一下午,导致没时间搞这题,其实这题不难,昨天我还看到个更绝望的,有个人为了找第二题的错误数据,专门写了个暴力对拍贪心,赛后知道正解后估计绝望....

题意:有n个数初始值为0,也有m个操作,每次操作 L R v,表示把区间[ L, R ]中小于 v 的数a[ i ]改为 v,区间 L 和 R 以及 v 都是用一个蛇皮函数(不知道为啥简单的事要搞的这么麻烦)求出,m次操作结束后,求所有的a[ i ]*i的异或值。

思路:标程的思路有点骚,我完全想不到,只能用线段树才能勉强维持得了生活这样子,把区间的值改为v,然后每次求一个点,这个不难,但是要把区间小于v的数改为v,有点麻烦,我用三颗线段树a min max分别表示区间的值以及最大值最小值,每次更新时,如果min[ o ]大于等于v,就不用继续更新了,这样可以加快速度,否则会超时,如果到了符合条件的区间了,必须得max[ o ]<=v,才更新区间,否则就更新儿子。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1e6+10;
const int inf=1e9;
unsigned int x,y,z,w;
int a[maxn],_max[maxn],_min[maxn];
const int mod=(1<<30);
int n,m;
unsigned int func()
{
	x=x^(x<<11);
	x=x^(x>>4);
	x=x^(x<<5);
	x=x^(x>>14);
	w=x^y^z;
	x=y;
	y=z;
	z=w;
	return z;
}
void pushdown(int o,int ls,int rs)
{
	if(a[o]>=0)
	{
		a[ls]=a[rs]=a[o];
		_max[ls]=_max[rs]=_min[ls]=_min[rs]=a[o]; 
		a[o]=-1;
	}
}
void pushup(int o,int ls,int rs)
{
	_max[o]=max(_max[o],max(_max[ls],_max[rs]));
	if(_min[ls]==-1&&_min[rs]!=-1)
	_min[o]=min(_min[o],_min[rs]);
	else if(_min[rs]==-1&&_min[ls]!=-1)
	_min[o]=min(_min[o],_min[ls]);
	else if(_min[ls]!=-1&&_min[rs]!=-1)
	_min[o]=min(_min[ls],_min[rs]);
}
void update(int l,int r,int o,int ql,int qr,int v)
{
	int ls=o*2,rs=o*2+1,m=(l+r)/2;
	if(l>r||_min[o]>=v)return;
	if(l>=ql&&r<=qr)
	{
		if(_max[o]<=v)
		{
			a[o]=v;
			_max[o]=_min[o]=v;
		}
		else
		{
			pushdown(o,ls,rs);
			update(l,m,ls,ql,qr,v);
			update(m+1,r,rs,ql,qr,v);
			pushup(o,ls,rs);
		}
	}
	else
	{
		pushdown(o,ls,rs);
		if(ql<=m)
		update(l,m,ls,ql,qr,v);
		if(qr>m)
		update(m+1,r,rs,ql,qr,v);
		pushup(o,ls,rs);
	}
}
int query(int l,int r,int o,int k)
{
	if(l>r)return 0;
	if(a[o]>=0)
	return a[o];
	{
		int ls=o*2,rs=o*2+1,m=(l+r)/2;
		if(k<=m)
		return query(l,m,ls,k);
		else
		return query(m+1,r,rs,k);
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
		for(int i=0;i<maxn;i++)
		a[i]=-1,_max[i]=0,_min[i]=-1;
		for(int i=1;i<=m;i++)
		{
			int l=func()%n+1;
			int r=func()%n+1;
			if(l>r)swap(l,r);
			int v=func()%mod;
			update(1,n,1,l,r,v);
		}
		LL sum=0;
		for(int i=1;i<=n;i++)
		{
			LL tmp=query(1,n,1,i);
			tmp=tmp*i;
			sum^=tmp;
		}
		printf("%lld\n",sum);
	}
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/81478220
今日推荐