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;
    }
    
  • 相关阅读:
    格式化代码
    hexdump命令
    shell中+,*,[:space:]的用法
    Linux下安装Android的adb驱动-解决不能识别的问题
    android launcher3 home页简易分析
    LINUX 内核代码 errno 错误代码提示 /include/asm/errno.h
    关于mtk Android打开串口权限问题
    关于android MTK相机L版本,切换屏幕比例后,分辨率随之改变,但重新进入相机后原有分辨率不再生效问题
    关于android应用闪屏的几种情况
    Android 笔记
  • 原文地址:https://www.cnblogs.com/chanme/p/3997481.html
Copyright © 2011-2022 走看看