洛谷 P3976 [TJOI2015]旅游

亡梦爱人 提交于 2020-04-01 13:54:04

树剖维护,注意方向(\(a \rightarrow b \neq b \rightarrow a\))。

#include <cstdio>
#define UP_TO_DOWN 0
#define DOWN_TO_UP 1

typedef bool qtype;

const int MAXN = 5e4 + 19;

class Query{
	private:
		int min, max, sub;	
	public:
		Query(){
			min = 0x3f3f3f3f, max = -0x3f3f3f3f, sub = 0;
		}
		Query(int __min, int __max, int __sub){
			min = __min, max = __max, sub = __sub;
		}
		Query operator^=(const Query& b){
			sub = sub > b.sub ? sub : b.sub;
			sub = sub > (b.max - min) ? sub : (b.max - min);
			min = min < b.min ? min : b.min;
			max = max > b.max ? max : b.max;
		}
		Query operator^(const Query& b)const{
			Query res = *this;
			res ^= b;
			return res;
		}
		int data(void){
			return sub;
		}
};

class SegmentTree{
	private:
		struct Node{
			int l, r;
			int min, max, subl, subr;
			int tag;
		}tr[MAXN << 2];
		int __min(const int& a, const int& b){
			return a < b ? a : b;
		}
		int __max(const int& a, const int& b){
			return a > b ? a : b;
		}
		void push_down(int node){
			if(tr[node].tag){
				tr[node << 1].min += tr[node].tag;
				tr[node << 1].max += tr[node].tag;
				tr[node << 1].tag += tr[node].tag;
				tr[node << 1 | 1].min += tr[node].tag;
				tr[node << 1 | 1].max += tr[node].tag;
				tr[node << 1 | 1].tag += tr[node].tag;
				tr[node].tag = 0;
			}
		}
		void push_up(int node){
			tr[node].min = __min(tr[node << 1].min, tr[node << 1 | 1].min);
			tr[node].max = __max(tr[node << 1].max, tr[node << 1 | 1].max);
			tr[node].subl = tr[node << 1 | 1].max - tr[node << 1].min;
			tr[node].subl = __max(tr[node].subl, tr[node << 1].subl);
			tr[node].subl = __max(tr[node].subl, tr[node << 1 | 1].subl);
			tr[node].subr = tr[node << 1].max - tr[node << 1 | 1].min;
			tr[node].subr = __max(tr[node].subr, tr[node << 1].subr);
			tr[node].subr = __max(tr[node].subr, tr[node << 1 | 1].subr);
		}
		void build(int node, int l, int r, int *w){
			tr[node].l = l, tr[node].r = r;
			if(l == r){
				tr[node].max = w[l];
				tr[node].min = w[l];
				tr[node].subl = 0;
				tr[node].subr = 0;
				return;
			}
			int mid = (l + r) >> 1;
			build(node << 1, l, mid, w);
			build(node << 1 | 1, mid + 1, r, w);
			push_up(node);
		}
		void modify(int node, int l, int r, const int& val){
			if(tr[node].l >= l && tr[node].r <= r){
				tr[node].min += val;
				tr[node].max += val;
				tr[node].tag += val;
				return;
			}
			push_down(node);
			int mid = (tr[node].l + tr[node].r) >> 1;
			if(l <= mid)
				modify(node << 1, l, r, val);
			if(r > mid)
				modify(node << 1 | 1, l, r, val);
			push_up(node);
		}
		Query query(int node, int l, int r, qtype q){
			if(tr[node].l >= l && tr[node].r <= r){
				int sub;
				if(q == UP_TO_DOWN)
					sub = tr[node].subl;
				else if(q == DOWN_TO_UP)
					sub = tr[node].subr;
				return Query(tr[node].min, tr[node].max, sub);
			}
			push_down(node);
			Query res;
			int mid = (tr[node].l + tr[node].r) >> 1;
			if(l <= mid){
				if(q == UP_TO_DOWN)
					res = res ^ query(node << 1, l, r, q);
				else if(q == DOWN_TO_UP)
					res = query(node << 1, l, r, q) ^ res;
			}
			if(r > mid){
				if(q == UP_TO_DOWN)
					res = res ^ query(node << 1 | 1, l, r, q);
				else if(q == DOWN_TO_UP)
					res = query(node << 1 | 1, l, r, q) ^ res;
			}
			return res;
		}
	public:
		void build(int l, int r, int *w){
			build(1, l, r, w);
		}
		void modify(int l, int r, const int& val){
			modify(1, l, r, val);
		}
		Query query(int l, int r, qtype q){
			return query(1, l, r, q);
		}
}myTree;

struct Edge{
	int to, next;
}edge[MAXN << 1];

int cnt, head[MAXN];

inline void add(int from, int to){
	edge[++cnt].to = to;
	edge[cnt].next = head[from];
	head[from] = cnt;
}

int n, q, p[MAXN], z[MAXN];

int ind;
int fa[MAXN], son[MAXN], dep[MAXN], size[MAXN], dfn[MAXN], top[MAXN]; 

void dfs1(int node, int f){
	fa[node] = f, dep[node] = dep[f] + 1, size[node] = 1;
	int max = 0;
	for(int i = head[node]; i; i = edge[i].next)
		if(edge[i].to != f){
			dfs1(edge[i].to, node);
			size[node] += size[edge[i].to];
			if(size[edge[i].to] > max)
				max = size[edge[i].to], son[node] = edge[i].to;
		}
}

void dfs2(int node, int f, int t){
	dfn[node] = ++ind, top[node] = t;
	if(son[node])
		dfs2(son[node], node, t);
	for(int i = head[node]; i; i = edge[i].next)
		if(edge[i].to != f && edge[i].to != son[node])
			dfs2(edge[i].to, node, edge[i].to);
}

int query(int x, int y, const int& val){
	Query l, r;
	while(top[x] != top[y]){
		if(dep[top[x]] > dep[top[y]])
			myTree.modify(dfn[top[x]], dfn[x], val),
			l = l ^ myTree.query(dfn[top[x]], dfn[x], DOWN_TO_UP), x = fa[top[x]];
		else
			myTree.modify(dfn[top[y]], dfn[y], val),
			r = myTree.query(dfn[top[y]], dfn[y], UP_TO_DOWN) ^ r, y = fa[top[y]];
	}
	if(dep[x] < dep[y])
		myTree.modify(dfn[x], dfn[y], val),
		l = l ^ myTree.query(dfn[x], dfn[y], UP_TO_DOWN);
	else
		myTree.modify(dfn[y], dfn[x], val),
		r = myTree.query(dfn[y], dfn[x], DOWN_TO_UP) ^ r;
	return (l ^ r).data();
}

int main(){
	std::scanf("%d", &n);
	for(int i = 1; i <= n; ++i)
		std::scanf("%d", p + i);
	for(int u, v, i = 1; i < n; ++i){
		std::scanf("%d%d", &u, &v);
		add(u, v);
		add(v, u);
	}
	dfs1(1, 0);
	dfs2(1, 0, 1);
	for(int i = 1; i <= n; ++i)
		z[dfn[i]] = p[i];
	myTree.build(1, n, z);
	std::scanf("%d", &q);
	for(int a, b, v, i = 1; i <= q; ++i){
		std::scanf("%d%d%d", &a, &b, &v);
		std::printf("%d\n", query(a, b, v));
	}
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!