Glad You Came
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1375 Accepted Submission(s): 553
Problem Description
Steve has an integer array a of length n (1-based). He assigned all the elements as zero at the beginning. After that, he made m operations, each of which is to update an interval of a with some value. You need to figure out ⨁ni=1(i⋅ai) after all his operations are finished, where ⨁ means the bitwise exclusive-OR operator.
In order to avoid huge input data, these operations are encrypted through some particular approach.
There are three unsigned 32-bit integers X,Y and Z which have initial values given by the input. A random number generator function is described as following, where ∧ means the bitwise exclusive-OR operator, << means the bitwise left shift operator and >> means the bitwise right shift operator. Note that function would change the values of X,Y and Z after calling.
Let the i-th result value of calling the above function as fi (i=1,2,⋯,3m). The i-th operation of Steve is to update aj as vi if aj<vi (j=li,li+1,⋯,ri), where
li=min((f[3i−2] mod n)+1,(f[3i−1] mod n)+1)
ri=max((f[3i−2] mod n)+1,(f[3i−1] mod n)+1)
vi=f[3i] mod 2^30(i=1,2,⋯,m).
Input
The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains five space-separated integers n,m,X,Y and Z.
1≤T≤100, 1≤n≤10^5, 1≤m≤5⋅10^6, 0≤X,Y,Z<2^30.
It is guaranteed that the sum of n in all the test cases does not exceed 106 and the sum of m in all the test cases does not exceed 5⋅107.
Output
For each test case, output the answer in one line.
Sample Input
4
1 10 100 1000 10000
10 100 1000 10000 100000
100 1000 10000 100000 1000000
1000 10000 100000 1000000 10000000
Sample Output
1031463378
1446334207
351511856
47320301347
Hint
In the first sample, a = [1031463378] after all the operations. In the second sample, a = [1036205629, 1064909195, 1044643689, 1062944339, 1062944339, 1062944339, 1062944339, 1057472915, 1057472915, 1030626924] after all the operations.
题目大意:
输入一个T代表有T组输入。
每一组有输入n,m,A,B,C
先利用题目给的随机生成函数生成3m组fi,li,ri,vi
对数组a进行3m次更新操作,a数组初始全为0,每次将li,ri区间内小于vi的数更新为vi。
最后求 ⨁ni=(i⋅ai) 对面每一个i*ai求异或和
由于有区间操作联想到可以使用线段树更新
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(x, y) (x > y ? (x) : (y))
#define min(x, y) (x < y ? (x) : (y))
using namespace std;
const int maxn = 100002,maxm = 5000001;
unsigned n,x,y,z,w,mod=1<<30,f[3*maxm];
unsigned long long sum = 0;
///线段树结构体
struct node{int l,r;unsigned Min,lazy;}T[maxn*4];
void nextInt(int &x){char c;do c=getchar();while (c<'0'||c>'9');x=c-'0';while ('0'<=(c=getchar())&&c<='9') x=x*10+c-'0';}
///输入
void nextUnsigned(unsigned &x){char c;do c=getchar();while (c<'0'||c>'9');x=c-'0';while ('0'<=(c=getchar())&&c<='9') x=x*10+c-'0';
}
///输出
void Out(unsigned long long a){if(a>9)Out(a/10);putchar(a%10+'0');}
///题目给的随机生成函数
unsigned getRand(){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;}
///建树
void build(int v,int l,int r)
{
T[v].l=l,T[v].r=r,T[v].lazy=0,T[v].Min=0;
if(l==r)return ;
int mid = (l+r)>>1;
build(v<<1,l,mid);
build(v<<1|1,mid+1,r);
}
///线段树区间更新
void add(int v,int l,int r,unsigned value)
{
if(T[v].Min>=value)return ; ///如果当前区间的最小值大于等于要更新的值直接结束
if(T[v].l==l&&T[v].r==r)
{
T[v].Min = max(value,T[v].Min);
T[v].lazy = max(value,T[v].lazy);
return ;
}
int mid=(T[v].l+T[v].r)>>1;
if(T[v].lazy)
{
T[v<<1].Min = max(T[v].lazy,T[v<<1].Min);
T[v<<1|1].Min = max(T[v].lazy,T[v<<1|1].Min);
T[v<<1].lazy = max(T[v].lazy,T[v<<1].lazy);
T[v<<1|1].lazy= max(T[v].lazy,T[v<<1|1].lazy);
T[v].lazy=0;
}
if(r<=mid)
{
add(v<<1,l,r,value);
}
else
{
if(l>mid)
{
add(v<<1|1,l,r,value);
}
else
{
add(v<<1,l,mid,value);
add(v<<1|1,mid+1,r,value);
}
}
T[v].Min=min(T[v<<1].Min,T[v<<1|1].Min);
}
///线段树询问
void query(int v,int l,int r)
{
if(l==r) ///每次查询到底
{
sum = sum^((unsigned long long)l*(unsigned long long)T[v].Min);
return ;
}
int mid=(T[v].l+T[v].r)>>1;
if(T[v].lazy)
{
T[v<<1].Min = max(T[v].lazy,T[v<<1].Min);
T[v<<1|1].Min = max(T[v].lazy,T[v<<1|1].Min);
T[v<<1].lazy = max(T[v].lazy,T[v<<1].lazy);
T[v<<1|1].lazy= max(T[v].lazy,T[v<<1|1].lazy);
T[v].lazy=0;
}
if(r<=mid)
{
query(v<<1,l,r);
}
else
{
if(l>mid)
{
query(v<<1|1,l,r);
}
else
{
query(v<<1,l,mid);
query(v<<1|1,mid+1,r);
}
}
}
int main()
{
int t,m,i;
unsigned l,r,v;
scanf("%d",&t);
while(t--)
{
///输入n,m,x,y,z
sum = 0;
nextUnsigned(n),nextInt(m);
nextUnsigned(x),nextUnsigned(y),nextUnsigned(z);
///生成f数组
for(i=1; i<=3*m; i++)f[i]=getRand();
///建树
build(1,1,n);
///一边生成数据一遍更新线段树
for(i=1; i<=m; i++)
{
l = f[3*i-2]%n+1,r = f[3*i-1]%n+1;
v = f[3*i]%mod;
if(l<r)
add(1,l,r,v);
else
add(1,r,l,v);
}
///最后查询
query(1,1,n);
Out(sum);
puts("");
}
return 0;
}