DTOJ#5144. Easiest

题目

给定一个长度为 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 n106
对于 100 % 100\% 100% 的数据,满足 n ≤ 1 0 7 n \leq 10^7 n107

题解

由于区间被清空之和就不会再被计算了,所以我们考虑并查集,对于每次操作,将 [ 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值