題意:
給你一個函數,用它求出長度爲3*m的數組,a數組一開始全爲0,有m個操作:l, r, v都可以用公式算出來,[l, r]區間內把所有小於v的a[i]替換成v。求出 [1,n]區間內的所有 (i*a[i]) 的異或和。
題解:
利用線段樹記錄區間的最大值和最小值,每次修改和查詢維護一下。如果最大值小於v就往下更新
剪枝:如果區間內的最小值大於v就不用走了,直接回去。
最後求出異或和。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define mem(a) memset(a, 0, sizeof(a))
#define mid (tree[root].l+tree[root].r)/2
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const int maxn = 1e5+10;
const int maxm = 5e6+10;
const int mod = 1 << 30;
struct Tree{
int l, r, minn, maxx, lazy;
}tree[maxn << 2];
int n, m;
ui x, y, z, w, f[maxm*3], a[maxn];
void build_tree(int l, int r, int root){
tree[root].l = l;
tree[root].r = r;
tree[root].minn = 0;
tree[root].maxx = 0;
tree[root].lazy = 0;
//cout<<l<<" "<<mid<<" "<<r<<endl;
if(r == l){
return;
}
build_tree(l, mid, root << 1);
build_tree(mid+1, r, (root << 1) | 1);
}
void push_up(int root){
tree[root].minn = min(tree[root << 1].minn, tree[(root << 1) | 1].minn);
tree[root].maxx = max(tree[root << 1].maxx, tree[(root << 1) | 1].maxx);
}
void push_down(int root){
if(tree[root].lazy){
tree[root << 1].lazy = tree[root].lazy;
tree[(root << 1) | 1].lazy = tree[root].lazy;
tree[root << 1].minn = tree[root].lazy;
tree[(root << 1) | 1].minn = tree[root].lazy;
tree[root << 1].maxx = tree[root].lazy;
tree[(root << 1) | 1].maxx = tree[root].lazy;
tree[root].lazy = 0;
}
}
void update_tree(int l, int r, int root, ui v){
if(tree[root].minn >= v){
return;
}
if(l <= tree[root].l && r >= tree[root].r){
if(tree[root].maxx < v){
tree[root].maxx = v;
tree[root].minn = v;
tree[root].lazy = v;
return;
}
}
push_down(root);
if(r <= mid){
update_tree(l, r, root << 1, v);
}
else if(l >= mid+1){
update_tree(l, r, (root << 1) | 1, v);
}
else{
update_tree(l, mid, root << 1, v);
update_tree(mid+1, r, (root << 1) | 1, v);
}
push_up(root);
}
void query_tree(int l, int r, int root){
if(tree[root].maxx == tree[root].minn){
for(int i = l; i <= r; i++){
a[i] = tree[root].maxx;
}
return;
}
push_down(root);
if(r <= mid){
query_tree(l, r, root << 1);
}
else if(l >= mid+1){
query_tree(l, r, (root << 1) | 1);
}
else{
query_tree(l, mid, root << 1);
query_tree(mid+1, r, (root << 1) | 1);
}
}
ui RNG61(){
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;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d %d %u %u %u", &n, &m, &x, &y, &z);
for(int i = 1; i <= m * 3; i++){
f[i] = RNG61();
}
build_tree(1, n, 1);
ui l, r, v;
for(int i = 1; i <= m; i++){
ui temp1 = f[i*3-2] % n + 1;
ui temp2 = f[i*3-1] % n + 1;
l = min(temp1, temp2);
r = max(temp1, temp2);
v = f[i*3] % mod;
update_tree(l, r, 1, v);
}
ll ans = 0;
query_tree(1, n, 1);
for(int i = 1; i <= n; i++){
ans ^= ((ll)i * (ll)a[i]);
}
printf("%lld\n", ans);
}
}