2018 Multi-University Training Contest 5 1007:Glad You Came(线段树)

题目链接

题目大意:

给出n个数(a1....an)一开始为0,然后给一个公式生成3m个数,在每次操作中根据另一个公式得到 l,r和v 在al..al+1..ar中如果ai<v,ai=v; 输出最后这n个数先乘自己的下标再异或的结果。

解题思路:

线段树维护n个数的最小值,在每次操作中区间更新,m次操作完后异或得出结果。(记得剪枝)

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
typedef long long ll;

struct node{
	
	int lazy;
	ll value;
	
}a[maxn<<2];

unsigned x,y,z,w;
ll ans;

unsigned func(){
	x^=x<<11;
	x^=x>>4;
	x^=x<<5;
	x^=x>>14;
	w=x^(y^z);
	x=y;
	y=z;
	z=w;
	return z;
}

void pushup(int rt){
	a[rt].value=min(a[rt<<1].value,a[rt<<1|1].value);
}

void bulid(int l,int r,int rt){
	a[rt].lazy=0;a[rt].value=0;
	if(l==r){
		return ;
	}
	int m=(l+r)>>1;
	bulid(l,m,rt<<1);
	bulid(m+1,r,rt<<1|1);
	pushup(rt);
}

void pushdown(int rt){
	if(a[rt].lazy){
		if(a[rt<<1].lazy<a[rt].lazy) a[rt<<1].lazy=a[rt].lazy;
		if(a[rt<<1].value<a[rt].lazy) a[rt<<1].value=a[rt].lazy;
		if(a[rt<<1|1].lazy<a[rt].lazy) a[rt<<1|1].lazy=a[rt].lazy;
		if(a[rt<<1|1].value<a[rt].lazy) a[rt<<1|1].value=a[rt].lazy;
		a[rt].lazy=0;
	}
}

void update(int l,int r,int L,int R,int rt,int c){
	if(a[rt].value>=c) return;//剪枝
	if(l>=L&&r<=R){
		if(a[rt].value<c){
			a[rt].value=c;
			a[rt].lazy=c;
		}
		
		return;
	}
	pushdown(rt);
	int m=(l+r)>>1;
	if(L<=m) update(l,m,L,R,rt<<1,c);
	if(R>m) update(m+1,r,L,R,rt<<1|1,c);
	pushup(rt);
			
}


void query(int l,int r,int rt){
	if(l==r){		
		ans^=(l*a[rt].value);
		return;
	}
	pushdown(rt);
	int m=(l+r)>>1;
	query(l,m,rt<<1);
	query(m+1,r,rt<<1|1);
}


int main(){
	int t,n,m;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
		bulid(1,n,1);
		
		while(m--){
			ll X=func();
			ll Y=func();
			ll c=func()%(1<<30);
			int l=min(X%n+1,Y%n+1);
			int r=max(X%n+1,Y%n+1);			
			update(1,n,l,r,1,c);
		}
		ans=0;
		query(1,n,1);
		printf("%lld\n",ans);
	}
	return 0;
}

线段树水题。。

加油加油

猜你喜欢

转载自blog.csdn.net/weixin_40800935/article/details/81487072
今日推荐