码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5002 Tree(LCT)

时间:2014-09-28 00:22:00      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   ar   for   sp   div   on   c   

今天做了一道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;
}

 

HDU5002 Tree(LCT)

标签:blog   io   os   ar   for   sp   div   on   c   

原文地址:http://www.cnblogs.com/chanme/p/3997481.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!