原题:hdu 6356
解析:
太杂了,所以那部分就不解释了,去杂后就是一个区间更新的问题
每次更新l,r,v,区间内比v小的数会变成v
主要思路就是记下区间的min,如果一个更新区间的最小值都比v大就说明不用更新从而起到一个剪枝的作用
代码:
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int mod=(1<<30);
const int maxn=100005;
typedef unsigned ll;
ll f[15000000], x,y,z;
int n,m;
unsigned rng()
{
unsigned t;
x^=x<<11;
x^=x>>4;
x^=x<<5;
x^=x>>14;
t=x;
x=y;
y=z;
z=x^y^t;
return z;
}
struct node{
int maxx,minn,lazy;
}e[maxn<<2];
void pushdown(int rt){
if(e[rt].lazy){
e[lson].lazy=e[rt].lazy;
e[rson].lazy=e[rt].lazy;
e[lson].maxx=e[rt].lazy;
e[rson].maxx=e[rt].lazy;
e[lson].minn=e[rt].lazy;
e[rson].minn=e[rt].lazy;
e[rt].lazy=0;
}
}
void update(int nowl,int nowr,int l,int r,int rt,ll aim){
if(e[rt].minn>=aim)return;//key
if(nowl>=l&&nowr<=r){
if(e[rt].maxx<=aim){
e[rt].maxx=aim;
e[rt].minn=aim;
e[rt].lazy=aim;
return ;
}
else if(e[rt].minn>=aim){
return ;
}
}
pushdown(rt);
int mid=(nowl+nowr)/2;
if(mid>=l) update(nowl,mid,l,r,lson,aim);
if(mid<r) update(mid+1,nowr,l,r,rson,aim);
e[rt].maxx=max(e[lson].maxx,e[rson].maxx);
e[rt].minn=min(e[lson].minn,e[rson].minn);
}
ll query(int nowl,int nowr,int l,int r,int rt){
if(nowl>=l&&nowr<=r){
return e[rt].maxx;
}
pushdown(rt);
int mid=(nowl+nowr)/2;
if(mid>=l) return query(nowl,mid,l,r,lson);
if(mid<r) return query(mid+1,nowr,l,r,rson);
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
memset(e,0,sizeof(e));
for(int i=1;i<=3*m;i++)
f[i]=rng();
for(int i=1;i<=m;i++){
int l=min(f[3*i-2]%n+1,f[3*i-1]%n+1);
int r=max(f[3*i-2]%n+1,f[3*i-1]%n+1);
ll aim=f[3*i]%mod;
update(1,n,l,r,1,aim);
}
unsigned long long ans=0;
for(int i=1;i<=n;i++){
unsigned long long nows=query(1,n,i,i,1);
ans^=(i*nows);
}
cout<<ans<<endl;
}
}