zoukankan      html  css  js  c++  java
  • 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:
    ",++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
    ");
    				else printf("%d %d
    ", ans.first, ans.second);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java学习开篇
    《我的姐姐》
    世上本无事,庸人自扰之
    这48小时
    补觉
    淡定
    es java api 设置index mapping 报错 mapping source must be pairs of fieldnames and properties definition.
    java mongodb groupby分组查询
    linux 常用命令
    mongodb too many users are authenticated
  • 原文地址:https://www.cnblogs.com/chanme/p/3997481.html
Copyright © 2011-2022 走看看