Sample Input
4
1 10 100 1000 10000
10 100 1000 10000 100000
100 1000 10000 100000 1000000
1000 10000 100000 1000000 10000000
Sample Output
1031463378
1446334207
351511856
47320301347
题意:函数生成f数列,a数列初始化为0,通过公式得到(l,r,v),表示将数列a的l到r区间值更新为max(a[i],v),最后输出所有a[i]*i的异或值
思路:线段树T了,应该是可以用但是我写的不够优秀吧,区间问题,所有更新结束以后输出一次值,ST比较合适,第一次用ST,但是要注意,这题是倒着的ST,是已知一个大的区间,更新小区间的最大值,可以看下面的题解。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 100005
using namespace std;
typedef unsigned long long ll;
ll stmax[maxn][20];//stmax[i][j]表示i到i+2^j-1区间的最大值
int LOG[maxn];
int n,m;
const unsigned long long mod=1<<30;
unsigned x,y,z,w;
unsigned tang(){
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 InitSt(){
for(int j=19;j;j--){
for(int i=1;i+(1<<j)-1<=n;i++){
stmax[i][j-1]=max(stmax[i][j-1],stmax[i][j]);
stmax[i+(1<<(j-1))][j-1]=max(stmax[i+(1<<(j-1))][j-1],stmax[i][j]);
}
}
}
int main(){
int t;
scanf("%d",&t);
LOG[2]=1;
for(int i=3;i<maxn;i++){
LOG[i]=LOG[i>>1]+1;
}//这里如果不预处理,而是直接求会超时
while(t--){
cin>>n>>m>>x>>y>>z;
memset(stmax,0,sizeof(stmax));
for(int i=1;i<=m;i++){
int l=tang()%n+1;
int r=tang()%n+1;
ll w=tang()%mod;
if(l>r)swap(l,r);
//int d=(int)((double)log(r-l+1.0)/log(2.0)); 这样求超时
int d=LOG[r-l+1];
stmax[l][d]=max(stmax[l][d],w);
stmax[r-(1<<d)+1][d]=max(stmax[r-(1<<d)+1][d],w);
}
InitSt();
ll ans=0;
for(ll i=1;i<=n;i++){
ans^=(stmax[i][0]*i);
}
cout<<ans<<endl;
}
return 0;
}