题目
给定一个长度为
n
n
n 的序列,第
i
i
i 号元素下标为 i。
有
q
q
q 次操作,每次给定一个区间下标为
[
l
,
r
]
[l, r]
[l,r],求该区间的元素和并将该
区间的所有元素删去(不改变剩余元素的下标),输出所有操作答案的异或
和,当区间
[
l
,
r
]
[l, r]
[l,r] 内没有元素的时候跳过该操作
给定
n
,
q
,
z
n, q, z
n,q,z你需要调用
n
n
n 次
g
e
n
(
)
gen()
gen() 函数获得序列,再调用
2
q
2q
2q 次获得每
次操作
[
l
,
r
]
[l, r]
[l,r],得到的
l
,
r
l, r
l,r 需要对
n
n
n 取模再加一,若获得的
l
>
r
l > r
l>r,则交换
l
,
r
l, r
l,r
const int N = 1e9 ;
unsigned x = 123456789 , y = 362436069 , z ;
unsigned gen ( )
{
unsigned t ;
x ^= x << 16; x ^= x >> 5 ; x ^= x << 1 ;
t = x ; x = y ; y = z ; z = t ^ x ^ y ;
return z % N + 1 ;
}
你需要注意的是, z z z 为 u n s i g n e d i n t unsigned int unsignedint
数据范围
对于
40
%
40\%
40% 的数据,满足
n
≤
1
0
6
n \leq 10^6
n≤106
对于
100
%
100\%
100% 的数据,满足
n
≤
1
0
7
n \leq 10^7
n≤107
题解
由于区间被清空之和就不会再被计算了,所以我们考虑并查集,对于每次操作,将 [ l , r ] [l,r] [l,r]内的集合全部合并,权值计算只需要合并时考虑一下这个集合是不是只有一个数即可。
代码
#include<bits/stdc++.h>
#define ll long long
const int m=1e7+5;
unsigned x=123456789,y=362436069,z,t,N=1e9;
unsigned e(){x^=x<<16;x^=x>>5;x^=x<<1;t=x;x=y;y=z;z=t^x^y;return z%N+1;}
int n,q,l,r,i,k;
ll s[m],f[m],A,S;
int g(int x){return (f[x]==x)?x:f[x]=g(f[x]);}
int main(){
std::cin>>n>>q>>z;
for(i=1;i<=n;++i)s[i]=e(),f[i]=i;f[n+1]=n+1;
while(q--){l=e()%n+1,r=e()%n+1;S=0;if(l>r)std::swap(l,r);for(i=g(l),k=g(i+1);i<=r;i=k,k=g(i+1))S+=s[i],f[i]=k;A^=S;}
std::cout<<A;
}