题目描述:
给你一个长度为n的最开始为0的数以及m个更新操作以及数据生成器参数X,Y,Z。每次操作,将由数据生成器生成出li,ri,vi。让你从区间[li,ri]中,将所有小于vi的数变为vi。最后让你求从1到n的 i*ai的亦或和。
分析:区间操作优先考虑线段树 , 那线段树存储什么数值呢? 我们知道如果l ,r 的最大值<=val , 那整个l区间都要改成val , 如果最小值>=val 那这个区间就不用修改 ; 那不是这种情况怎么办呢?不可能是for一遍吧 , 其实只要一次跟新操作就好 , 线段树的区间更新是将整课树都遍历一遍 ,所以我们只要在遍历的过程中判断是否到达叶子结点就好拉;
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <math.h> #include <queue> #define MAXN 5000001 #define inf 0x3f3f3f3f using namespace std; unsigned int x,y,z,w,v,b[MAXN*3]; int n,m; long long ans; unsigned int fun() { 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; } struct node{ int l,r;//区间[l,r] int add;//区间的延时标记 int mx; //区间最大值 int mn; //区间最小值 }tree[MAXN<<2];//一定要开到4倍多的空间 void pushup(int index){ tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx); tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn); } void pushdown(int index){ //说明该区间之前更新过 //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新 if(tree[index].add > 0){ //替换原来的值 tree[index<<1].mx = tree[index].add; tree[index<<1|1].mx = tree[index].add; tree[index<<1].mn = tree[index].add; tree[index<<1|1].mn = tree[index].add; tree[index<<1].add = tree[index].add; tree[index<<1|1].add = tree[index].add; tree[index].add = 0; } } void build(int l,int r,int index){ tree[index].l = l; tree[index].r = r; tree[index].add = 0;//刚开始一定要清0 if(l == r){ tree[index].mn = tree[index].mx = 0; return ; } int mid = (l+r)>>1; build(l,mid,index<<1); build(mid+1,r,index<<1|1); pushup(index); } void updata(int l,int r,int index,int val){ if(tree[index].l==tree[index].r)///到达叶子节点 { tree[index].mn=max(tree[index].mn , val); tree[index].mx=max(tree[index].mx , val); return ; } if(l <= tree[index].l && r >= tree[index].r){ if(tree[index].mx<=val) { tree[index].mn = val; tree[index].mx = val; tree[index].add = val;//延时标记 return ; } if(tree[index].mn>=val) return ; } if(tree[index].mn>=val) return ; pushdown(index); int mid = (tree[index].l+tree[index].r)>>1; if(l <= mid){ updata(l,r,index<<1,val); } if(r > mid){ updata(l,r,index<<1|1,val); } pushup(index); } int query(int l,int r,int index,int pos){ if(l==r) { return tree[index].mn; } int mid=(l+r)>>1; pushdown(index); if(pos<=mid) return query(l,mid , index<<1 , pos); else return query(mid+1,r ,index<<1|1 , pos); } int main() { int t,l,r; scanf("%d",&t); while(t--) { scanf("%d%d%u%u%u",&n , &m , &x , &y , &z); build(1,n,1); for(int i=1 ; i<=max(n,3*m) ; i++)///数据生成器 b[i] = fun(); for(int i=1 ; i<=m ; i++) { l = min(b[3*i-2]%n+1 , b[3*i-1]%n+1); r = max(b[3*i-2]%n+1 , b[3*i-1]%n+1); v = b[3*i]%(1<<30); updata(l,r,1,v); } ans=0; for(int i=1 ; i<=n ; i++) ans^=(long long)i*query(1,n,1,i); printf("%lld ",ans); } return 0; }