SPOJ QTREE6 lct
题目链接
岛娘出的题。还是比較easy的
#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 = 100005; const int inf = 10000000; struct Node *null; struct Node { Node *fa, *ch[2]; int id; int s[2];//s[0] this虚边所连的全部子树的连续白色点数总和(不是链) int col; int ls[2], rs[2], siz; //ls[0]是对于这条链 最上端向下的连续白色点数 int Ls[2], Rs[2]; //Ls[0]是对于这棵子树 与最上端点相连的连续白色点数 bool rev; inline void clear(int _col, int _id) { fa = ch[0] = ch[1] = null; siz = 1; rev = 0; id = _id; col = _col; for (int i = 0; i < 2; i++) { ls[i] = rs[i] = s[i] = 0; } } 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]++; Ls[i] += s[i]; 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]++; Rs[i] += s[i]; 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] += p->ch[1]->Ls[i]; if (q != null) for (int i = 0; i < 2; i++) 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++; } 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] += 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, 0); null->siz = 0; for (int i = 1; i <= n; i++) { node[i] = tail++; node[i]->clear(1, i); } dfs(1, 1); rd(q); int u, v; while (q--) { rd(u); rd(v); if (!u) { node[v]->access(); pt(max(node[v]->Rs[0], node[v]->Rs[1])); puts(""); } else { node[v]->access(); node[v]->col ^= 1; node[v]->push_up(); } } } return 0; }
SPOJ QTREE6 lct相关推荐
- SPOJ QTREE5 lct
题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set ...
- SPOJ OTOCI 动态树 LCT
SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...
- [BZOJ3637][LCT]Qtree6
BZOJ3637 LCT维护连通块的一个题 一个简单的想法是直接两个LCT分别维护黑白森林,改变点的时候就把所有出边linkcut一下 然而菊花图可以随便卡 被卡的关键在于这个算法是以点的出度为时间复 ...
- 洛谷 - P6292 区间本质不同子串个数(SAM+LCT+线段树)
题目链接:点击查看 题目大意:给出一个长度为 n 的字符串,再给出 m 次询问,每次询问需要回答区间 [ l , r ] 内有多少个本质不同的字符串 题目分析:首先简化模型,回顾一下如何求解 &quo ...
- SPOJ QTREE
QTREE /*题目大意:维护一棵树,允许修改边权以及查询链上最大值题解:我们将边权转为点权,标记在深度较深的点上,树链剖分后用线段树处理即可 */ #include <cstdio> # ...
- 【Qtree】Query on a tree系列LCT解法
Qtree1-7 Qtree1 裸的树链剖分,当然也可以用LCT写,就不说什么了... Qtree2 倍增lca,当然也可以用LCT写,就不说什么了... Qtree3 裸的树链剖分,当然也可以用LC ...
- QTREE系列1,4,5,6,7 LCT
QTREE1 题意: 给出一棵N(N <= 10000)个点的树,要求支持: 1.改变第i条边的权值 2.求a->b上的最大边权 解: 直接树剖或LCT即可 代码 1.LCT(660ms) ...
- Qtree LCT系列
Qtree1,2,3暂缺 Qtree4思路 总是有机房大佬问我怎么做(抄题解不就好了吗?),那我就讲一讲我紊乱的思路吧. 应该不难想到边权下放到子节点,有了这个基础,我们对细节的处理就不用那么模糊了. ...
- LCT (Link-cut-tree)
文章目录 LCT LCT定义 学习资料 四种操作 解决的问题 LCT 快退役了学一波以前听过很多次但没时间学的东西 LCT定义 学习资料 建议读论文 维基百科 https://en.wikipedia ...
最新文章
- 1,Composite UI Application Block (CAB) 介绍
- Android 自定义长按响应时间
- QTextCodec中的setCodecForTr等终于消失了 (Qt5)
- 【赠送】IT技术视频教程,白拿不谢!思科、华为、红帽、数据库、云计算等等
- instancetype和id的区别
- 循环序列模型 —— 1.8 带有神经网络的梯度消失
- Atitit.attilax重要案例 项目与解决方案与成果 v6 qa15
- linux安装使用7zip
- 将python图表放入ppt_如何在ppt中嵌入python图表(或图像)并刷新
- Linux 中复制问题,错误显示 cp:omitting directory
- 硬件电路设计之三极管和场效应管做开关管
- Android(一)
- work bench 建表时PK/NN/ UQ等的含义
- 深度优先搜索(DFS)与广度优先搜索(BFS)算法详解
- python 数据可视化工具--matplotlib
- 利用java解一元二次方程
- Pascal语言简介
- Android Studio禁用 install run
- 工程学导论之职业道德
- 以let开头的祈使句用法归纳