【线段树】 HDOJ 5274 Dylans loves tree

用dfs序构建线段树,然后用lca求出两点间路径的xor和。。。

#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 100005 
#define maxm 200005
#define eps 1e-7
#define mod 998244353
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

struct Edge
{
	int v;
	Edge *next;
}*H[maxn], *edges, E[maxm];

int anc[maxn][20];
int dep[maxn];
int in[maxn];
int out[maxn];
int a[maxn];
int sum[maxn << 4];
int lazy[maxn << 4];
const int M = 20;
int dfs_clock, n, m;

void addedges(int u, int v)
{
	edges->v = v;
	edges->next = H[u];
	H[u] = edges++;
}

void dfs(int u, int fa)
{
	dfs_clock++;
	in[u] = dfs_clock;
	anc[u][0] = fa;
	for(Edge *e = H[u]; e; e = e->next) if(e->v != fa) {
		int v = e->v;
		dep[v] = dep[u] + 1;
		dfs(v, u);
	}
	out[u] = dfs_clock;
}

int to(int u, int d)
{
	for(int i = M - 1; i >= 0; i--) if(dep[anc[u][i]] >= d) u = anc[u][i];
	return u;
}

int lca(int u, int v)
{
	if(dep[u] < dep[v]) swap(u, v);
	u = to(u, dep[v]);
	for(int i = M - 1; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
	return u == v ? u : anc[u][0];
}

void init()
{
	dfs_clock = 0;
	dfs(1, 1);
	for(int i = 1; i < M; i++)
		for(int j = 1; j <= n; j++)
			anc[j][i] = anc[anc[j][i-1]][i-1];
}

void pushup(int o)
{
	sum[o] = sum[ls] ^ sum[rs];
}

void pushdown(int o)
{
	if(lazy[o]) {
		sum[ls] ^= lazy[o];
		sum[rs] ^= lazy[o];
		lazy[ls] ^= lazy[o];
		lazy[rs] ^= lazy[o];
		lazy[o] = 0;
	}
}

void build(int o, int L, int R)
{
	lazy[o] = sum[o] = 0;
	if(L == R) return;
	int mid = (L + R) >> 1;
	build(lson);
	build(rson);
	pushup(o);
}

void update(int o, int L, int R, int ql, int qr, int v)
{
	if(ql <= L && qr >= R) {
		lazy[o] ^= v;
		sum[o] ^= v;
		return;
	}
	pushdown(o);
	int mid = (L + R) >> 1;
	if(ql <= mid) update(lson, ql, qr, v);
	if(qr > mid) update(rson, ql, qr, v);
	pushup(o);
}

int query(int o, int L, int R, int q)
{
	if(L == R) return sum[o];
	pushdown(o);
	int ans = 0, mid = (L + R) >> 1;
	if(q <= mid) ans = query(lson, q);
	else ans = query(rson, q);
	pushup(o);
	return ans;
}

void work()
{
	int u, v;
	scanf("%d%d", &n, &m);
	edges = E;
	memset(H, 0, sizeof H);
	for(int i = 1; i < n; i++) {
		scanf("%d%d", &u, &v);
		addedges(u, v);
		addedges(v, u);
	}
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]), a[i]++;
	init();
	build(1, 1, n);
	for(int i = 1; i <= n; i++) update(1, 1, n, in[i], out[i], a[i]);

	while(m--) {
		int kk;
		scanf("%d%d%d", &kk, &u, &v);
		if(kk) {
			int c = lca(u, v);
			int ans = query(1, 1, n, in[u]) ^ query(1, 1, n, in[v]) ^ a[c];
			if(ans) printf("%d\n", ans-1);
			else printf("-1\n");
		}
		else {
			++v;
			update(1, 1, n, in[u], out[u], a[u] ^ v);
			a[u] = v;
		}
	}
}

int main()
{
	int _;
	scanf("%d", &_);
	while(_--) work();
	
	return 0;
}


你可能感兴趣的:(线段树)