题目:http://acm.hdu.edu.cn/showproblem.php?pid=6356
题意:
给三个数X,Y,Z;
给定一个依赖于XYZ的随机数生成函数;
m个操作,每次让区间[Li,Ri]内的数ai=max(ai,v);
求⨁(i⋅ai),⨁是异或和;
分析:
法一:线段树
minv[x]记录区间最小值;
若minv[x]>=v,则剪枝(重点,不然TLE);
查询时每次查询到最底端(所以说像是假线段树!)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ul;
const int tmax=1e5+5;
const int tmax2=5e6+5;
ll ans;
ul n,X,Y,Z,W,ql,qr,v,p,minv[4*tmax];
ul rng()
{
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;
}
ul query(int x,int l,int r)
{
if(l==r) return minv[x];
int mid=l+(r-l)/2;
if(mid>=p) return query(x*2,l,mid);
if(mid<p) return query(x*2+1,mid+1,r);
}
void update(int x,int l,int r)
{
if(minv[x]>=v) return;
if(l==r)
{
minv[x]=max(minv[x],v);
return;
}
int mid=l+(r-l)/2;
if(mid>=ql) update(x*2,l,mid);
if(mid<qr) update(x*2+1,mid+1,r);
minv[x]=min(minv[x*2],minv[x*2+1]);
return;
}
int main()
{
int T,len,m,i;
scanf("%d",&T);
while(T--)
{
ans=0;
scanf("%u%d%u%u%u",&n,&m,&X,&Y,&Z);
memset(minv,0,sizeof(minv));
for(i=1;i<=m;i++)
{
ql=(rng()%n)+1;
qr=(rng()%n)+1;
v=rng()%(1<<30);
if(ql>qr) swap(ql,qr);
update(1,1,n);
}
for(i=1;i<=n;i++)
{
p=i;
ans=ans xor (1ll*i*query(1,1,n));
}
printf("%I64d\n",ans);
}
return 0;
}