0
点赞
收藏
分享

微信扫一扫

2017年第0届浙江工业大学之江学院程序设计竞赛决赛—I

Aliven888 2022-09-07 阅读 64


Problem I: qwb VS 去污棒

Time Limit: 2 Sec   Memory Limit: 256 MB

Submit: 35  

Solved: 11

[​Submit​​][​Status​​][​Web Board​​]


Description


qwb表白学姐失败后,郁郁寡欢,整天坐在太阳底下赏月。在外人看来,他每天自言自语,其实他在和自己的影子“去污棒”聊天。
去污棒和qwb互相出题考验对方,去污棒问了qwb这样一个问题:
现已知一个有n个正整数的序列a[1],a[2]...a[n],接下来有m个操作

操作一共有两种:

1.在序列末尾添加一个数x。


2.查询suf[p] xor x的最大值,其中xor是异或 ,l<=p<=r,

suf[t]表示从t开始的后缀的异或和,即

suf[t]=a[t] xor a[t+1] xor ...xor a[len],len为序列长度。



Input


第一行一个整数T(<=5),表示一共有T组数据。

每组数据第一行两个整数n(<=200000),m(<=200000),意义如上所述。


随后一行有n个数,表示初始序列。

随后m行,每行表示一个操作。


操作有两种,1: x 表示在末尾添加一个x,2: l r x表示查询suf[p] xor x的最大值,其中l<= p <= r,


所有数及x不超过224

所有操作合法。


Output


每组测试数据的第一行输出"Case x:",x为数据组数的标号,从1开始。

接下来,对每个操作2输出一行答案。


Sample Input

1
5 5
1 2 3 4 5
2 1 3 4
1 10
1 7
2 4 4 5
2 1 5 19

Sample Output

Case 1:
6
9
31

【分析】


主席树模板...套一下就好了...


注意一下求前缀和的时候,要加入一个0表示最开始的前缀和。


【代码】


#include<cstdio>  
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 600010
#define N maxn*27

using namespace std;

int lch[N],rch[N],size[N],root[maxn];
int n,m,tot,T,sum;
char s[5];

int modify(int pre,int i,int x)
{
int now=++tot;
if (i==0)
{
lch[now]=rch[now]=0;size[now]=size[pre]+1;
}
else
{
int mid=((x>>(i-1))&1);
if (mid==0)
{
rch[now]=rch[pre];lch[now]=modify(lch[pre],i-1,x);
}
else
{
lch[now]=lch[pre];rch[now]=modify(rch[pre],i-1,x);
}
size[now]=size[lch[now]]+size[rch[now]];
}
return now;
}

int query(int root1,int root2,int i,int x)
{
if (i==0) return 0;
int mid=((x>>(i-1))&1);
if (mid==0)
{
if (size[rch[root2]]-size[rch[root1]]) return (1<<(i-1))+query(rch[root1],rch[root2],i-1,x);
else return query(lch[root1],lch[root2],i-1,x);
}
else
{
if (size[lch[root2]]-size[lch[root1]]) return (1<<(i-1))+query(lch[root1],lch[root2],i-1,x);
else return query(rch[root1],rch[root2],i-1,x);
}
}

int main()
{
int pp;scanf("%d",&pp);
for (int p=1;p<=pp;p++)
{
printf("Case %d:\n",p);
scanf("%d%d",&n,&T);
root[0]=lch[0]=rch[0]=size[0]=0;
root[0]=modify(root[0],25,0);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);sum^=x;
root[i]=modify(root[i-1],25,sum);
}
while (T--)
{
int l,r,x;
scanf("%s",s+1);
if (s[1]=='1')
{
scanf("%d",&x);
sum^=x;
n++;root[n]=modify(root[n-1],25,sum);
}
else
{
scanf("%d%d%d",&l,&r,&x);
l--;r--;
printf("%d\n",query(root[l-1],root[r],25,sum^x));
}
}
}
return 0;
}



举报

相关推荐

0 条评论