逃票的chanming(1)

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值