题目链接
题目大意:
给出n个数(a1....an)一开始为0,然后给一个公式生成3m个数,在每次操作中根据另一个公式得到 l,r和v 在al..al+1..ar中如果ai<v,ai=v; 输出最后这n个数先乘自己的下标再异或的结果。
解题思路:
线段树维护n个数的最小值,在每次操作中区间更新,m次操作完后异或得出结果。(记得剪枝)
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
typedef long long ll;
struct node{
int lazy;
ll value;
}a[maxn<<2];
unsigned x,y,z,w;
ll ans;
unsigned func(){
x^=x<<11;
x^=x>>4;
x^=x<<5;
x^=x>>14;
w=x^(y^z);
x=y;
y=z;
z=w;
return z;
}
void pushup(int rt){
a[rt].value=min(a[rt<<1].value,a[rt<<1|1].value);
}
void bulid(int l,int r,int rt){
a[rt].lazy=0;a[rt].value=0;
if(l==r){
return ;
}
int m=(l+r)>>1;
bulid(l,m,rt<<1);
bulid(m+1,r,rt<<1|1);
pushup(rt);
}
void pushdown(int rt){
if(a[rt].lazy){
if(a[rt<<1].lazy<a[rt].lazy) a[rt<<1].lazy=a[rt].lazy;
if(a[rt<<1].value<a[rt].lazy) a[rt<<1].value=a[rt].lazy;
if(a[rt<<1|1].lazy<a[rt].lazy) a[rt<<1|1].lazy=a[rt].lazy;
if(a[rt<<1|1].value<a[rt].lazy) a[rt<<1|1].value=a[rt].lazy;
a[rt].lazy=0;
}
}
void update(int l,int r,int L,int R,int rt,int c){
if(a[rt].value>=c) return;//剪枝
if(l>=L&&r<=R){
if(a[rt].value<c){
a[rt].value=c;
a[rt].lazy=c;
}
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(l,m,L,R,rt<<1,c);
if(R>m) update(m+1,r,L,R,rt<<1|1,c);
pushup(rt);
}
void query(int l,int r,int rt){
if(l==r){
ans^=(l*a[rt].value);
return;
}
pushdown(rt);
int m=(l+r)>>1;
query(l,m,rt<<1);
query(m+1,r,rt<<1|1);
}
int main(){
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
bulid(1,n,1);
while(m--){
ll X=func();
ll Y=func();
ll c=func()%(1<<30);
int l=min(X%n+1,Y%n+1);
int r=max(X%n+1,Y%n+1);
update(1,n,l,r,1,c);
}
ans=0;
query(1,n,1);
printf("%lld\n",ans);
}
return 0;
}
线段树水题。。
加油加油