HDU5002 Tree(LCT)

今天做了一道LCT模板题之后忽然间好像记起来LCT的模板怎么用了,于是就把上次网络赛的一道LCT补一下。典型的删边,加边操作,还有路径加和路径set为一个数。维护的是路径第二大以及它有多少个,后来想想其实确实是挺好写的,就是维护最大值以及次大值,然后upd的时候把儿子合并回去就好了,当时觉得不会做实在是想太多了。

#pragma warning(disable:4996)

#include <iostream>

#include <cstring>

#include <string>

#include <cstdio>

#include <vector>

#include <algorithm>

#include <map>

using namespace std;



#define ll long long

#define maxn 200000

#define INF 0x3f3f3f3f

#define INP INF+1

#define MP make_pair



void merge(int mxx[2], int nxx[2], int pval, int pnum)

{

	if (pval>mxx[0]){

		mxx[1] = mxx[0]; nxx[1] = nxx[0];

		mxx[0] = pval; nxx[0] = pnum;

	}

	else if (pval == mxx[0]){

		nxx[0] += pnum;

	}

	else if (pval>mxx[1]){

		mxx[1] = pval; nxx[1] = pnum;

	}

	else if(pval==mxx[1]){

		nxx[1] += pnum;

	}

}





struct Node

{

	Node *p, *ch[2];

	bool rev;

	int val;

	int mx[2], num[2];

	int add, cov;

	int size;

	bool isRoot;

	Node *fa;

	Node(){

		val = 0; rev = 0;

		add = 0; cov = INP;

		mx[0] = mx[1] = -INF;

		num[0] = num[1] = 0;

		size = 0;

	}

	void setc(Node *c, int d){

		ch[d] = c;

		c->p = this;

	}

	bool d(){

		return p->ch[1] == this;

	}

	void upd(){

		size = ch[0]->size + ch[1]->size + 1;

		mx[0] = ch[0]->mx[0]; num[0] = ch[0]->num[0];

		mx[1] = ch[0]->mx[1]; num[1] = ch[0]->num[1];

		merge(mx, num, val, 1);

		merge(mx, num, ch[1]->mx[0], ch[1]->num[0]);

		merge(mx, num, ch[1]->mx[1], ch[1]->num[1]);

	}

	void revIt(){

		rev ^= 1;

		swap(ch[0], ch[1]);

	}

	void addIt(int vx){

		add += vx;

		val += vx;

		if (mx[0] != -INF) mx[0] += vx;

		if (mx[1] != -INF) mx[1] += vx;

	}

	void setIt(int vx){

		add = 0;

		cov = vx;

		val = vx;

		mx[0] = vx; num[0] = size;

		mx[1] = -INF; num[1] = 0;

	}

	void relax();

	void setRoot(Node *f);

}Tnull, *null = &Tnull;



void Node::setRoot(Node *f){

	fa = f;

	isRoot = true;

	p = null;

}



void Node::relax(){

	if (cov != INP){

		for (int i = 0; i<2; ++i){

			if (ch[i] != null) ch[i]->setIt(cov);

		}

		cov = INP;

	}

	if (add != 0){

		for (int i = 0; i < 2; i++){

			if (ch[i] != null) ch[i]->addIt(add);

		}

		add = 0;

	}

	if (rev){

		for (int i = 0; i < 2; i++){

			if (ch[i] != null) ch[i]->revIt();

		}

		rev = 0;

	}

}



Node mem[maxn], *C = mem;



Node *make(int v){

    C->size=1;

	C->val = v;

	C->rev = 0; C->add = 0;

	C->cov = INP;

	C->mx[0] = v; C->num[0] = 1;

	C->mx[1] = -INF; C->num[1] = 0;

	C->ch[0] = C->ch[1] = null; C->isRoot = true;

	C->p = null;

	C->fa = null;

	return C++;

}



void rot(Node *t){

	Node *p = t->p;

	p->relax();

	t->relax();

	bool d = t->d();

	p->p->setc(t, p->d());

	p->setc(t->ch[!d], d);

	t->setc(p, !d);

	p->upd();

	if (p->isRoot){

		p->isRoot = false;

		t->isRoot = true;

		t->fa = p->fa;

	}

}



void pushTo(Node*t) {

	static Node*stk[maxn]; int top = 0;

	while (t != null) {

		stk[top++] = t;

		t = t->p;

	}

	for (int i = top - 1; i >= 0; --i) stk[i]->relax();

}



void splay(Node*u, Node*f = null) {

	pushTo(u);

	while (u->p != f) {

		if (u->p->p == f)

			rot(u);

		else

			u->d() == u->p->d() ? (rot(u->p), rot(u)) : (rot(u), rot(u));

	}

	u->upd();

}



Node *v[maxn];

vector<int> E[maxn];

int n, nQ;



int que[maxn], fa[maxn], qh = 0, qt = 0;

int wht[maxn];



void bfs()

{

	qh = qt = 0;

	que[qt++] = 1;

	fa[1] = -1;

	while (qh < qt){

		int u = que[qh++];

		for (int i = 0; i < E[u].size(); i++){

			int e = E[u][i];

			if (e != fa[u]){

				fa[e] = u;

				v[e]->fa = v[u];

				que[qt++] = e;

			}

		}

	}

}



Node *expose(Node *u)

{

	Node *v;

	for (v = null; u != null; v = u, u = u->fa){

		splay(u);

		u->ch[1]->setRoot(u);

		u->setc(v, 1);

		v->fa = u;

	}

	return v;

}



void makeRoot(Node *u)

{

	expose(u);

	splay(u);

	u->revIt();

}



void addEdge(Node *u, Node *v)

{

	makeRoot(v);

	v->fa = u;

}



void delEdge(Node *u, Node *v)

{

	makeRoot(u);

	expose(v); splay(u); u->setc(null, 1); u->upd();

	v->setRoot(null);

}



void addPath(Node *u, Node *v, int ax)

{

	makeRoot(u);

	expose(v);

	splay(v);

	v->addIt(ax);

}



void setPath(Node *u, Node *v, int ax)

{

	makeRoot(u);

	expose(v);

	splay(v);

	v->setIt(ax);

}



pair<int, int> queryPath(Node *u, Node *v){

	makeRoot(u);

	expose(v);

	splay(v);

	return MP(v->mx[1], v->num[1]);

}



Node *find_root(Node *u)

{

	expose(u); splay(u);

	while (u->ch[0] != null){

		u = u->ch[0];

	}

	splay(u); return u;

}



int main()

{

	int T; cin >> T;int ca=0;

	while (T--)

	{

		C = mem;

		scanf("%d%d", &n, &nQ);

		for (int i = 1; i <= n; i++){

			scanf("%d", wht + i);

			v[i] = make(wht[i]);

		}

		for (int i = 0; i <= n; i++) E[i].clear();

		int ui, vi;

		for (int i = 0; i < n - 1; i++){

			scanf("%d%d", &ui, &vi);

			E[ui].push_back(vi); E[vi].push_back(ui);

		}

		bfs();

		int cmd, xi, yi, ai, bi;

		Node *nx, *ny, *na, *nb;

		printf("Case #%d:\n",++ca);

		while (nQ--){

			scanf("%d", &cmd);

			if (cmd == 1) scanf("%d%d%d%d", &xi, &yi, &ai, &bi);

			else if (cmd == 2 || cmd == 3) scanf("%d%d%d", &ai, &bi, &xi);

			else scanf("%d%d", &ai, &bi);



			if (cmd == 1){

				nx = v[xi]; ny = v[yi];

				na = v[ai]; nb = v[bi];

				delEdge(nx, ny);

				addEdge(na, nb);

			}

			else if (cmd == 2){

				nx = v[ai]; ny = v[bi];

				setPath(nx, ny, xi);

			}

			else if (cmd == 3){

				nx = v[ai]; ny = v[bi];

				addPath(nx, ny, xi);

			}

			else{

				nx = v[ai]; ny = v[bi];

				pair<int, int> ans = queryPath(nx, ny);

				if (ans.first <= -INF) printf("ALL SAME\n");

				else printf("%d %d\n", ans.first, ans.second);

			}

		}

	}

	return 0;

}

 

你可能感兴趣的:(tree)