题目
经过一波玄学的操作得到左端点
,右端点
,
多组数据,求
分析
这道题首先先放玄学操作
int answer(){
x^=(x<<11); x^=(x>>4); x^=(x<<5); x^=(x>>14);
uit w=x^y^z; x=y; y=z; z=w; return z;
}
f1=answer(); f2=answer(); v=answer()%1073741824;
l=min(f1%n+1,f2%n+1); r=max(f1%n+1,f2%n+1);
不多说玄学操作QAQ
然后其它呢,怎样把答案从每个区间缩到单点,线段树?理论上查询
会超时,然并卵,所以就用一种神奇的逆ST表
代码
#include <cstdio>
#include <algorithm>
typedef unsigned uit;
uit f[100001][17],ln[100001],t,n,m,x,y,z;
uit in(){
uit ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(long long ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
uit answer(){
x^=(x<<11); x^=(x>>4); x^=(x<<5); x^=(x>>14);
uit w=x^y^z; x=y; y=z; z=w; return z;
}
int main(){
t=in();
for (register uit i=2;i<=100000;i++) ln[i]=ln[i>>1]+1;
while (t--){
uit n,m,l,r,f1,f2,v,k; long long ans=0ll;
n=in(); m=in(); x=in(); y=in(); z=in();
while (m--){
f1=answer(); f2=answer(); v=answer()%1073741824;
l=std::min(f1%n+1,f2%n+1); r=std::max(f1%n+1,f2%n+1);
k=ln[r-l+1]; f[l][k]=std::max(f[l][k],v);
f[r-(1<<k)+1][k]=std::max(f[r-(1<<k)+1][k],v);//首先得到两个区间增加
}
for (register uit j=ln[n];j>=1;j--)//RMQ
for (register uit i=1;i<=n;i++){
f[i][j-1]=std::max(f[i][j-1],f[i][j]);
if (i+(1<<j-1)<=n) f[i+(1<<j-1)][j-1]=std::max(f[i+(1<<j-1)][j-1],f[i][j]);
f[i][j]=0;
}
for (register long long i=1;i<=n;i++) ans^=f[i][0]*i,f[i][0]=0;//求答案
if (ans) print(ans); else putchar('0'); putchar('\n');
}
return 0;
}