Description
这是一个神奇的国度。
这个国度一共有N个城市组成,让我们将他们编号为1~N,
这一天,chanming带着他的第一个月的工资K元来到了城市1。他想到城市N去寻找宝藏。qinhang3想跟chanming一起去,但是chanming并不想带他(太大只,逃票太明显)。于是他对qinhang3说,这样吧,你帮我解决这个问题,我们就一起走,不然就只能友尽了,这个题目是这样的:
有一个长度为N的序列,初始值都为0。
现在有2种不同操作:
操作0: 读入p,q,v,并且a[p] ^= v, a[p + 1] ^= v, .. ,a[q] ^= v;
操作1: 读入p,q,输出s = a[p] ^ a[p + 1] ^ a[p + 2]..^a[q]的结果;
*@.@*...还好qinhang3找到了一位神犇帮忙,不用东张西望了,就是你!如果你能解决这个问题的话,qinhang3将送给你一个精美的气球作为报答。
Input
单组数据
第一行为两个数N,M,分别表示序列的个数和操作的个数
接下来M行,第一个数op,表示操作的种类,如果为0,读入p,q,v,如果为1,读入p,q
N <= 500000
M <= 500000
0 < v < 2^30
Output
对于个op为1,输出结果。
Sample Input
100 30 2 6 30 1 2 71 2 3
Sample Output
7
题意:区间异或某值,询问区间和。
思路:线段树维护区间异或值,懒惰标记区间异或某值。只用PushDown,不用PushUp。比赛的时候用结构体写的线段树
一直过不了、、、赛后用数组改写才AC~~~
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define lson (id<<1)
#define rson (id<<1|1)
#define maxn (500080<<2)
#define mid ((ll+rr)>> 1)
int sum[maxn],add[maxn];
int len(int ll,int rr)
{
return rr-ll+1;
}
void scanf_(int & num)
{
char in;
while((in = getchar()) > '9' || in < '0');
num = in - '0';
while(in = getchar(),in >= '0' && in <= '9')
num *= 10,num += in-'0';
}
void PushDown(int id,int ll,int rr)
{
if(add[id])
{
add[lson] ^= add[id];
add[rson] ^= add[id];
if(len(ll,mid)&1)
sum[lson] ^= add[id];
if(len(mid+1,rr)&1)
sum[rson] ^= add[id];
add[id] = 0;
}
}
void update(int id,int ll,int rr,int l,int r,int v)
{
if(len(l,r)&1)
sum[id] ^= v;
if(ll == l && rr == r)
{
add[id] ^= v;
return;
}
PushDown(id,ll,rr);
if(r <= mid)
update(lson,ll,mid,l,r,v);
else if(l > mid)
update(rson,mid+1,rr,l,r,v);
else
{
update(lson,ll,mid,l,mid,v);
update(rson,mid+1,rr,mid+1,r,v);
}
}
int query(int id,int ll,int rr,int l,int r)
{
if(ll == l && rr == r)
return sum[id];
PushDown(id,ll,rr);
if(r <= mid)
return query(lson,ll,mid,l,r);
else if(l > mid)
return query(rson,mid+1,rr,l,r);
else return query(lson,ll,mid,l,mid)^query(rson,mid+1,rr,mid+1,r);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
scanf_(n);scanf_(m);
while(m--)
{
int ope,l,r,v;
//scanf("%d",&ope);
scanf_(ope);
if(ope == 1)
{
//scanf("%d%d",&l,&r);
scanf_(l);
scanf_(r);
printf("%d\n",query(1,1,n,l,r));
}
else
{
//scanf("%d%d%d",&l,&r,&v);
scanf_(l);
scanf_(r);
scanf_(v);
update(1,1,n,l,r,v);
}
}
return 0;
}
比赛时的TLE版本:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <stack>
using namespace std;
#define min(a,b) a > b?b:a;
#define max(a,b) a > b?a:b;
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define LL long long int
#define maxn 1000080
void scanf_(int & num)
{
char in;
while((in = getchar()) > '9' || in < '0');
num = in - '0';
while(in = getchar(),in >= '0' && in <= '9')
num *= 10,num += in-'0';
}
struct ST
{
int l,r,set,sum,fuck;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l ,st[id].r = r;
st[id].set = 0;
if((r-l+1)&1) st[id].fuck = 1;
else st[id].fuck = 0;
st[id].sum = 0;
if(l == r)
{
return;
}
int mid = (l+r) >> 1;
buildtree(lson);
buildtree(rson);
}
/*
void PushUp(int id)
{
st[id].sum = st[id<<1].sum ^ st[id<<1|1].sum;
}
*/
void PushDown(int id)
{
if(st[id].set)
{
if(!st[id<<1].set)
st[id<<1].set = st[id].set;
else st[id<<1].set ^= st[id].set;
if(!st[id<<1|1].set)
st[id<<1|1].set = st[id].set;
else st[id<<1|1].set ^= st[id].set;
if(st[id<<1].fuck)
st[id<<1].sum ^= st[id].set;
if(st[id<<1|1].fuck)
st[id<<1|1].sum ^= st[id].set;
st[id].set = 0;
}
}
void Update(int id,int l,int r,int v)
{
if((r-l+1)&1) st[id].sum ^= v;
if(st[id].l == l && st[id].r == r)
{
if(!st[id].set)
{
st[id].set = v;
}
else st[id].set ^= v;
//if(st[id].fuck) st[id].sum ^= v;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
Update(id<<1,l,r,v);
else if(st[id<<1|1].l <= l)
Update(id<<1|1,l,r,v);
else
{
Update(id<<1,l,st[id<<1].r,v);
Update(id<<1|1,st[id<<1|1].l,r,v);
}
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id]. r == r)
return st[id].sum;
PushDown(id);
if(st[id<<1].r >= r)
return query(id<<1,l,r);
else if(st[id<<1|1].l <= l)
return query(id<<1|1,l,r);
return query(id<<1,l,st[id<<1].r)^(query(id<<1|1,st[id<<1|1].l,r));
}
int main()
{
int n,m;
//scanf_(n);scanf_(m);
scanf("%d%d",&n,&m);
buildtree(1,1,n);
while(m--)
{
int ope,l,r,v;
scanf("%d",&ope);
//scanf_(ope);
if(ope == 1)
{
scanf("%d%d",&l,&r);
//scanf_(l);
//scanf_(r);
printf("%d\n",query(1,l,r));
}
else
{
scanf("%d%d%d",&l,&r,&v);
//scanf_(l);
//scanf_(r);
//scanf_(v);
Update(1,l,r,v);
}
}
return 0;
}