题意:首先一个长度为n的a数组,全为0。一个长度为3m的b数组,通过题目给的随机生成,然后根据题目给出的公式,区间【l,r】和一个数v对于区间内的数a【i】=max(a【i】,v),计算出a[i]的每个值,然后求与i的异或和。
正解是用反向RMQ,更新每段区间,然后压到每一项上。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn =1e5+10;
int mm[maxn*5];
int f[20][maxn*5];
unsigned X,Y,Z;
unsigned RNG61()
{
X=X^(X<<11);
X=X^(X>>4);
X=X^(X<<5);
X=X^(X>>14);
unsigned W=X^(Y^Z);
X=Y;
Y=Z;
Z=W;
return Z;
}
void update(int l,int r,int v)
{
int k=mm[r-l+1];
f[k][l]=max(f[k][l],v);
f[k][r-(1<<k)+1]=max(f[k][r-(1<<k)+1],v);
}
int main()
{
mm[2] = 1;
for(int i = 3; i < maxn; i++)
mm[i] = mm[i >> 1] + 1;
int t;
scanf("%d", &t);
while(t--)
{
int n, m;
cin>>n>>m>>X>>Y>>Z;
for(int j=0;j<20;j++)
{
for(int i=1;i<=n;i++)
{
f[j][i]=0;
}
}
for(int i = 1; i <= m; i++)
{
int x=RNG61()%n+1,y=RNG61()%n+1,z=RNG61()%(1<<30);
update(min(x,y),max(x,y),z);
}
for(int i=19;i>=1;i--)
{
for(int j=1;j+(1<<i)-1<=n;j++)
{
f[i-1][j]=max(f[i-1][j],f[i][j]);
f[i-1][j+(1<<i-1)]=max(f[i-1][j+(1<<i-1)],f[i][j]);
}
}
long long ans=0;
for(int i=1;i<=n;i++)
{
ans=ans^(i*(long long)f[0][i]);
}
printf("%lld\n",ans);
}
return 0;
}