HDU 5274(LCA + 线段树)

Dylans loves tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 747    Accepted Submission(s): 144

Problem Description

Dylans is given a tree with  nodes.

All nodes have a value .Nodes
on tree is numbered by .

Then he is given  questions
like that:

①:change
node  value
to

②:For
all the value in the path from  to ,do
they all appear even times?

For each ② question,it guarantees that there is at most one value that appears odd times on the path.

,
the value  and

Input

In the first line there is a test number .

( and
there is at most one testcase that )

For each testcase:

In the first line there are two numbers  and .

Then in the next  lines
there are pairs of  that
stand for a road from  to .

Then in the next line there are  numbers  stand
for value.

In the next  lines
there are three numbers.

Output

For each question ② in each testcase,if the value all appear even times output "-1",otherwise output the value that appears odd times.

Sample Input

1
3 2
1 2
2 3
1 1 1
1 1 2
1 1 3

Sample Output

-1
1

Hint

If you want to hack someone,N and Q in your testdata must smaller than 10000,and you shouldn‘t print any space in each end of the line.

Source

BestCoder Round #45

Recommend

hujie   |   We have carefully selected several similar problems for you:  5275 5272 5271 5270 5268

先考虑无改动的情况,令Xor[i]表示i到根节点路径上的异或和。则随意节点的(u,v)的异或和能够转化为Xor[u]^Xor[v]^a[LCA(u,v)].考虑改动的情况。改动节点u,仅仅会以u为根的子树的Xor值产生影响,由于一颗子树的dfs序是连续的我们非常自然的想到用线段树去维护他,pSeg[u]表示u在dfs序中的位置,siz[u]表示以u为根的子树大小,则这课颗子树相应的区间就是[pSeg[u],pSeg[u]+siz[u]-1],改动的时候仅仅须要将这段区间先异或上原来的值a[u],在异或上要变成的值y,然后改动a[u]
= y;两次异或能够一步到位。直接异或上a[u]^y即可。

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 10;
#define to first
#define next second
#define foreach(it,v) for(__typeof(v.begin()) it = v.begin(); it != v.end(); ++it)
int pos[maxn],d[20][maxn<<1],wid[maxn<<1],head[maxn];
int a[maxn],depth[maxn],sid,pSeg[maxn],siz[maxn],Xor[maxn];
typedef pair<int,int> Edge;
Edge edges[maxn<<1];
int tot = 0,e = 0;
void AddEdge(int u,int v)
{
	edges[++e] = make_pair(v,head[u]);head[u] = e;
	edges[++e] = make_pair(u,head[v]);head[v] = e;
}
void pre(int u,int fa,int dep = 0,int Xo = 0)
{
	Xo ^= a[u];
	Xor[++sid] = Xo;
	pSeg[u] = sid;
	siz[u] = 1;
	d[0][++tot] = u;
	if(!pos[u]) {
		pos[u] = tot;
		depth[u] = dep;
	}
	for(int i = head[u]; i ; i = edges[i].next) {
		int v = edges[i].to;
		if(v == fa) continue;
		pre(v,u,dep+1,Xo);
		siz[u] += siz[v];
		d[0][++tot] = u;
	}
}
void RMQ_init(int n)
{
	for(int i = 1,w = 1; i <= n; i++) {
		if((1<<w)<=i) w++;
		wid[i] = w - 1;
	}
	for(int i = 1; (1<<i) <= n; i++) {
		for(int j = 1; j + (1<<i) - 1 <= n; j++) {
			d[i][j] = depth[d[i-1][j]] < depth[d[i-1][j+(1<<(i-1))]] ? d[i-1][j] : d[i-1][j+(1<<(i-1))];
		}
	}
}
int LCA(int u,int v)
{
	u = pos[u];
	v = pos[v];
	if(u > v) swap(u,v);
	int k = wid[v-u+1];
	return depth[d[k][u]] < depth[d[k][v-(1<<k)+1]] ?

d[k][u] : d[k][v-(1<<k)+1];
}
int seg[maxn<<2];
int ql,qr,x;
void push_down(int o)
{
	seg[o<<1] ^= seg[o];
	seg[o<<1|1] ^= seg[o];
	seg[o] = 0;
}
void Modify(int o,int L,int R)
{
	if(ql<=L&&qr>=R) {
		seg[o] ^= x;
		return ;
	}
	push_down(o);
	int mid = (L+R)>>1;
	if(ql<=mid) Modify(o<<1,L,mid);
	if(qr>mid) Modify(o<<1|1,mid+1,R);
}
int Query(int o,int L,int R)
{
	if(L == R) {
		return Xor[L] ^ seg[o];
	}
	int mid = (L+R) >>1;
	push_down(o);
	if(x<=mid)return Query(o<<1,L,mid);
	return Query(o<<1|1,mid+1,R);
}
int main(int argc, char const *argv[])
{
	int T;scanf("%d",&T);
	while(T--) {
		int N,Q;scanf("%d%d",&N,&Q);
		e = sid = tot = 0;
		memset(head,0,sizeof(head[0])*(N+1));
		for(int i = 1; i < N; i++) {
			int u,v;scanf("%d%d",&u,&v);
			AddEdge(u,v);
		}
		for(int i = 1; i <= N; i++) {
			scanf("%d",a+i);
			++a[i];
		}
		pre(1,-1);
		RMQ_init(tot);
		memset(seg,0,sizeof(seg[0])*(2*N+10));
		while(Q--) {
			scanf("%d%d%d",&x,&ql,&qr);
			if(x==0) {
				qr++;
				int L = pSeg[ql], R = pSeg[ql] + siz[ql] - 1;
				x = a[ql] ^ qr;
				a[ql] = qr;
				ql = L,qr = R;
				Modify(1,1,N);
			}else {
				x = pSeg[ql];
				int ans = Query(1,1,N);
				x = pSeg[qr];
				ans ^= Query(1,1,N);
				ans ^= a[LCA(ql,qr)];
				if(ans==0)puts("-1");
				else printf("%d\n", ans-1);
			}
		}
	}
	return 0;
}
时间: 2024-11-03 21:17:18

HDU 5274(LCA + 线段树)的相关文章

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

hdu 1542 Atlantis(线段树)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6899    Accepted Submission(s): 3022 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 4864(2) 线段树

对task和machine的yi由小到大进行排序,然后对machine来跟task配对.当machine[].yi >= task[].yi时,就更新线段树,在1-1440上做线段树,线段树存的是task[].xi,同时用用优先队列保存task[].yi:当machine[].yi < task[].yi时,就查找 1到machine[].xi最大的值.如果存在最大值的话,把优先队列里的task[].yi取出来..这样一个machine就匹配到了一个最优的任务.还是看代码好好意会吧,细节挺多的