SPOJ QTREE7 lct

题目链接

已经在代码中注释了变量含义,感觉不难

inf好像不止|1e9| inf设成0x3f 才过。。

#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x <0) {
		putchar('-');
		x = -x;
	}
	if (x>9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair<int, int> pii;
const int N = 500005;
const int inf = 0x3f3f3f3f;
inline int First(multiset<int>&x) {
	return *x.rbegin();
}
inline int Second(multiset<int>&x) {
	multiset<int>::reverse_iterator it = x.rbegin();
	it++; return *it;
}
inline void Erase(multiset<int>&x, int val) {
	x.erase(x.find(val));
}
struct Node *null;
struct Node {
	Node *fa, *ch[2];
	int id;
	multiset<int>s[2];//s[0] this虚边所连的所有子树的连续白色点的最大值(不是链)
	int col;
	int ls[2], rs[2], siz, val;
	//ls[0]是对于这条链 最上端向下的连续白色点数
	int Ls[2], Rs[2];
	//Ls[0]是对于这棵子树 与最上端点相连的连续白色点的最大值
	bool rev;
	inline void clear(int _col, int _val, int _id) {
		fa = ch[0] = ch[1] = null;
		siz = 1;
		rev = 0;
		id = _id;
		col = _col;
		val = _val;
		for (int i = 0; i < 2; i++) {
			ls[i] = rs[i] = 0;
			Ls[i] = Rs[i] = -inf;
			s[i].clear();
			s[i].insert(-inf);
		}
	}
	inline void push_up() {
		if (this == null)return;
		siz = ch[0]->siz + ch[1]->siz + 1;
		for (int i = 0; i < 2; i++) {
			ls[i] = ch[0]->ls[i], rs[i] = ch[1]->rs[i];
			Ls[i] = ch[0]->Ls[i], Rs[i] = ch[1]->Rs[i];
			if (ch[0]->ls[i] == ch[0]->siz && i == col) {
				ls[i] = ch[0]->siz + 1 + ch[1]->ls[i];
				Ls[i] = max(Ls[i], val);
				Ls[i] = max(Ls[i], First(s[i]));
				Ls[i] = max(Ls[i], ch[1]->Ls[i]);
			}
			if (ch[1]->rs[i] == ch[1]->siz && i == col) {
				rs[i] = ch[1]->siz + 1 + ch[0]->rs[i];
				Rs[i] = max(Rs[i], val);
				Rs[i] = max(Rs[i], First(s[i]));
				Rs[i] = max(Rs[i], ch[0]->Rs[i]);
			}
		}
	}
	inline void push_down() {
		if (rev) {
			ch[0]->flip();
			ch[1]->flip();
			rev = 0;
		}
	}
	inline void setc(Node *p, int d) {
		ch[d] = p;
		p->fa = this;
	}
	inline bool d() {
		return fa->ch[1] == this;
	}
	inline bool isroot() {
		return fa == null || fa->ch[0] != this && fa->ch[1] != this;
	}
	inline void flip() {
		if (this == null)return;
		swap(ch[0], ch[1]);
		rev ^= 1;
	}
	inline void go() {//从链头开始更新到this
		if (!isroot())fa->go();
		push_down();
	}
	inline void rot() {
		Node *f = fa, *ff = fa->fa;
		int c = d(), cc = fa->d();
		f->setc(ch[!c], c);
		this->setc(f, !c);
		if (ff->ch[cc] == f)ff->setc(this, cc);
		else this->fa = ff;
		f->push_up();
	}
	inline Node*splay() {
		go();
		while (!isroot()) {
			if (!fa->isroot())
				d() == fa->d() ? fa->rot() : rot();
			rot();
		}
		push_up();
		return this;
	}
	inline Node* access() {//access后this就是到根的一条splay,并且this已经是这个splay的根了
		for (Node *p = this, *q = null; p != null; q = p, p = p->fa) {
			p->splay();
			if (p->ch[1] != null)
				for (int i = 0;i < 2;i++)
				{
					p->s[i].insert(p->ch[1]->Ls[i]);
				}
			if (q != null)
				for (int i = 0; i < 2; i++)
				{
					Erase(p->s[i], q->Ls[i]);
				}
			p->setc(q, 1);
			p->push_up();
		}
		return splay();
	}
	inline Node* find_root() {
		Node *x;
		for (x = access(); x->push_down(), x->ch[0] != null; x = x->ch[0]);
		return x;
	}
	void make_root() {
		access()->flip();
	}
	void cut() {//把这个点的子树脱离出去
		access();
		ch[0]->fa = null;
		ch[0] = null;
		push_up();
	}
	void cut(Node *x) {
		if (this == x || find_root() != x->find_root())return;
		else {
			x->make_root();
			cut();
		}
	}
	void link(Node *x) {
		if (find_root() == x->find_root())return;
		else {
			make_root(); fa = x;
		}
	}
};
Node pool[N], *tail;
Node *node[N];
int n, q;
struct Edge {
	int to, nex;
}edge[N << 1];
int head[N], edgenum;
void add(int u, int v) {
	Edge E = { v, head[u] };
	edge[edgenum] = E;
	head[u] = edgenum++;
}
int col[N], val[N];
void dfs(int u, int fa) {
	for (int i = head[u]; ~i; i = edge[i].nex) {
		int v = edge[i].to; if (v == fa)continue;
		node[v]->fa = node[u];
		dfs(v, u);
		for (int j = 0; j < 2; j++)
		{
			node[u]->s[j].insert(node[v]->Ls[j]);
		}
	}
	node[u]->push_up();
}
int main() {
	while (cin >> n) {
		memset(head, -1, sizeof head); edgenum = 0;
		for (int i = 1, u, v; i < n; i++) {
			rd(u); rd(v);
			add(u, v);add(v, u);
		}
		tail = pool;
		null = tail++;
		null->clear(-1, -inf, 0); null->siz = 0;
		for (int i = 1; i <= n; i++) rd(col[i]);
		for (int i = 1; i <= n; i++) rd(val[i]);
		for (int i = 1; i <= n; i++)
		{
			node[i] = tail++;
			node[i]->clear(col[i], val[i], i);
		}
		dfs(1, 1);
		rd(q); int u, v, w;
		while (q--) {
			rd(u); rd(v);
			if (0 == u) {
				node[v]->access();
				pt(max(node[v]->Rs[0], node[v]->Rs[1])); puts("");
			}
			else if (1 == u) {
				node[v]->access();
				node[v]->col ^= 1;
				node[v]->push_up();
			}
			else {
				rd(w);
				node[v]->access();
				node[v]->val = w;
				node[v]->push_up();
			}
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 18:18:51

SPOJ QTREE7 lct的相关文章

SPOJ QTREE3 lct裸题

题目链接 题意: 给定n个点 q个询问 下面n-1行给出树边,点有黑或白色,初始化为白色 下面q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑点的点标, 若不存在黑点则输出-1 思路: lct裸题 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #inc

SPOJ - OTOCI LCT

OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18141 Description Some time ago Mirko founded a new tourist agency named "Dreams of Ice". The agency purchased N icy islands near the S

SPOJ QTREE2 lct裸题

题目链接 题意: 给一棵树,有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #inclu

SPOJ QTREE2 lct

题目链接 题意: 给一棵树.有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #inclu

SPOJ QTREE4 lct

题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <s

SPOJ QTREE7

题意 一棵树,每个点初始有个点权和颜色 \(0 \ u\) :询问所有\(u,v\) 路径上的最大点权,要满足\(u,v\) 路径上所有点的颜色都相同 $1 ?u \(:反转\)u$ 的颜色 \(2 \ u \ w\) :把\(u\) 的点权改成\(w\) \(color_i∈[0,1],w_i∈[?10^9,10^9],n,m≤10^5\) Sol \(LCT\) 和\(QTREE6\)一样,黑白两棵\(LCT\) 不过这次我们用数据结构维护虚子树内的最大权的同色点 可以用\(multiset

SPOJ QTREE5 lct裸题

题目链接 对于每个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部最近的白点距离 rs:(链的下端点)距离链内部最近的白点距离 注意以上都是实边 虚边的信息用一个set维护. set维护的是对于每个不是链上,但是this的子树,那些子树中距离this最近的白点距离. #include <stdio.h> #include <string.h> #include <set> #include <algorithm> #include <i

SPOJ QTREE6 lct

题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <stack> #include <cstr

SPOJ QTREE5 lct

题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set维护的是对于每一个不是链上,可是this的子树,那些子树中距离this近期的白点距离. #include <stdio.h> #include <string.h> #include <set> #include <algorithm> #include <