题目: 传送门
思路: 除了卡常好像没什么好说的…如果直接用 max函数会T的很惨.基本就是 线段树维护最小值,然后对于更新操作加一些剪枝就可以了.
Ac_Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define fir first
#define sec second
using namespace std;
const int maxn = 1e5+7;
const int mod = (1<<30);
int n,m;
unsigned int x,y,z;
int tr[maxn<<2];
void build(int l,int r,int num) {
tr[num] = 0;
if(l==r) return ;
int mid = (l+r) >>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
}
void modify(int l,int r,int num,int le,int ri,int tmp) {
if(tr[num] > tmp) return ;
if(le<=l && r<=ri) {
tr[num] = tmp;
return ;
}
int mid = (l+r) >>1;
if(tr[num] > tr[num<<1]) tr[num<<1] = tr[num];
if(tr[num] > tr[num<<1|1]) tr[num<<1|1] = tr[num];
if(le<=mid) modify(l,mid,num<<1,le,ri,tmp);
if(mid< ri) modify(mid+1,r,num<<1|1,le,ri,tmp);
tr[num] = min(tr[num<<1],tr[num<<1|1]);
}
int quriy(int l,int r,int num,int pos) {
if(l==r) return tr[num];
int mid = (l+r) >>1;
if(tr[num] > tr[num<<1]) tr[num<<1] = tr[num];
if(tr[num] > tr[num<<1|1]) tr[num<<1|1] = tr[num];
if(pos<=mid) return quriy(l,mid,num<<1,pos);
else return quriy(mid+1,r,num<<1|1,pos);
tr[num] = min(tr[num<<1],tr[num<<1|1]);
}
unsigned int make() {
x = (x ^ (x<<11));
x = (x ^ (x>>4));
x = (x ^ (x<<5));
x = (x ^ (x>>14));
unsigned int w = (x^(y^z));
x = y;
y = z;
z = w;
return z;
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d%d%d%d",&n,&m,&x,&y,&z);
build(1,n,1);
for(int i=0;i<m;i++) {
unsigned int a = make();
unsigned int b = make();
unsigned int c = make();
modify(1,n,1,min(a%n+1,b%n+1),max(a%n+1,b%n+1),c%mod);
}
long long ans = 0;
for(int i=1;i<=n;i++) {
//cout<< quriy(1,n,1,i)<<endl;
ans ^= 1ll *quriy(1,n,1,i) * i;
}
printf("%lld\n",ans);
}
return 0;
}