输入n,m,x,y,z。根据题目中给出的程序,可以得到f数组。a数组初始值全为0,根据题意,对a数组进行m次修改。修改为,l,r区间内比v小的数均改为v。
思路:
维护区间的最小值和次小值,lazy更新。
线段树不会超时,大概是因为神奇的随机数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
const ll mod=1073741824;
unsigned x,y,z,w,a[N*200];
int n,m,l,r,v;
ll res;
ll mmin[N<<2],se[N<<2];
void pushup(int rt)
{
mmin[rt]=min(mmin[rt<<1],mmin[rt<<1|1]);
if(mmin[rt<<1]==mmin[rt<<1|1])
{
se[rt]=min(se[rt<<1],se[rt<<1|1]);
}
else
{
se[rt]=max(mmin[rt<<1],mmin[rt<<1|1]);
se[rt]=min(se[rt],min(se[rt<<1],se[rt<<1|1]));
}
}
void pushdown(int rt)
{
if(mmin[rt<<1]<=mmin[rt])
mmin[rt<<1]=mmin[rt];
if(mmin[rt<<1|1]<=mmin[rt])
mmin[rt<<1|1]=mmin[rt];
}
void build(int rt,int l,int r)
{
if(l==r)
{
mmin[rt]=0;
se[rt]=1083741824;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void change(int L,int R,int rt,int l,int r,int x)
{
if(x<=mmin[rt])
return;
if(L<=l&&R>=r&&se[rt]>=x)
{
mmin[rt]=x;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid)
change(L,R,rt<<1,l,mid,x);
if(R>mid)
change(L,R,rt<<1|1,mid+1,r,x);
pushup(rt);
}
unsigned f()
{
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 solve(int rt,int l,int r)
{
if(l==r)
{
res^=(mmin[rt]*l);
return;
}
pushdown(rt);
int mid=(l+r)>>1;
solve(rt<<1,l,mid);
solve(rt<<1|1,mid+1,r);
pushup(rt);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int i,j;
scanf("%d%d",&n,&m);
cin>>x>>y>>z;
for(i=1;i<=m*3;i++)
{
a[i]=f();
}
build(1,1,n);
for(i=1;i<=m;i++)
{
l=min(a[3*i-2]%n+1,a[3*i-1]%n+1);
r=max(a[3*i-2]%n+1,a[3*i-1]%n+1);
v=a[3*i]%mod;
change(l,r,1,1,n,v);
}
res=0;
solve(1,1,n);
printf("%lld\n",res);
}
return 0;
}
不用lazy标记,直接更新也可以过。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
const ll mod=1073741824;
unsigned x,y,z,w,a[N*200];
int n,m,l,r,v;
ll res;
ll mmin[N<<2];
void pushup(int rt)
{
mmin[rt]=min(mmin[rt<<1],mmin[rt<<1|1]);
}
void change(int L,int R,int rt,int l,int r,int x)
{
if(x<=mmin[rt])
return;
if(l==r)
{
mmin[rt]=x;
return;
}
int mid=(l+r)>>1;
if(L<=mid)
change(L,R,rt<<1,l,mid,x);
if(R>mid)
change(L,R,rt<<1|1,mid+1,r,x);
pushup(rt);
}
void solve(int rt,int l,int r)
{
if(l==r)
{
res^=(mmin[rt]*l);
return;
}
int mid=(l+r)>>1;
solve(rt<<1,l,mid);
solve(rt<<1|1,mid+1,r);
pushup(rt);
}
unsigned f()
{
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--)
{
int i,j;
scanf("%d%d%d%d%d",&n,&m,&x,&y,&z);
for(i=1;i<=m*3;i++)
{
a[i]=f();
}
memset(mmin,0,sizeof(mmin));
for(i=1;i<=m;i++)
{
l=min(a[3*i-2]%n+1,a[3*i-1]%n+1);
r=max(a[3*i-2]%n+1,a[3*i-1]%n+1);
v=a[3*i]%mod;
change(l,r,1,1,n,v);
}
res=0;
solve(1,1,n);
printf("%lld\n",res);
}
return 0;
}