题目链接

题意:

给定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>
#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 = 30005;
const int inf = 10000000;
struct Node *null;
struct Node{
Node *fa, *ch[2];
int size;
int val, ma, sum, id;
bool rev;
inline void put(){
printf("%d:id, %d,%d,%d (%d,%d) fa:%d \n", id, val, ma, sum, ch[0]->id, ch[1]->id, fa->id);
}
inline void clear(int _val, int _id){
fa = ch[0] = ch[1] = null;
size = 1;
rev = 0;
id = _id;
val = ma = sum = _val;
}
inline void push_up(){
size = 1 + ch[0]->size + ch[1]->size; sum = ma = val;
if (ch[0] != null) {
sum += ch[0]->sum;
ma = max(ma, ch[0]->ma);
}
if (ch[1] != null){
sum += ch[1]->sum;
ma = max(ma, ch[1]->ma);
}
}
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()->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;
void debug(Node *x){
if (x == null)return;
x->put();
debug(x->ch[0]);
debug(x->ch[1]);
}
inline void change(Node* x){
x->access();
x->val ^= 1;
x->push_up();
}
inline int ask(Node* x){
node[1]->make_root();
x->access();
node[1]->splay();
// for (int i = 1; i <= n; i++)debug(node[i]), putchar('\n');
Node *r = node[1];
if (r->sum == 0)return -1;
while (true){
if (r->ch[0]->sum == 0 && r->val)return r->id;
r = r->ch[r->ch[0]->sum==0];
}
}
struct Edge{
int from, to, nex;
}edge[N << 1];
int head[N], edgenum;
void add(int u, int v){
Edge E = { u, 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;
dfs(v, u);
node[v]->push_up();
node[v]->fa = node[u];
}
}
int main(){
while (cin>>n>>q){
memset(head, -1, sizeof head); edgenum = 0;
tail = pool;
null = tail++; null->clear(0, 0);
null->size = 0; null->sum = 0;
for (int i = 1; i <= n; i++) {
node[i] = tail++;
node[i]->clear(0, i);
}
for (int i = 1, u, v; i < n; i++){
rd(u); rd(v);
add(u, v); add(v, u);
}
dfs(1, 1);
int u, v;
while (q--){
rd(u); rd(v);
if (u == 0)change(node[v]);
else pt(ask(node[v])), putchar('\n');
}
}
return 0;
}
/*
9 8
1 2
1 3
2 4
2 9
5 9
7 9
8 9
6 8 1 3
0 8
1 6
1 7
0 2
1 9
0 2
1 9
*/

SPOJ QTREE3 lct的更多相关文章

  1. SPOJ QTREE3 Query on a tree again! ——Link-Cut Tree

    [题目分析] QTREE2,一看是倍增算法,太懒了,不写了.( ̄_, ̄ ) QTREE3,树链剖分可以做,发现链上的问题LCT也很好做. 要是子树问题貌似可以DFS序. 然后就成LCT模板题了. 考前 ...

  2. SPOJ - OTOCI LCT

    OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem. ...

  3. SPOJ QTREE4 lct

    题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #i ...

  4. Query on a tree again! SPOJ - QTREE3

    https://vjudge.net/problem/SPOJ-QTREE3 https://www.luogu.org/problemnew/show/P4116 一个log(LCT)比两个log( ...

  5. SPOJ QTREE2 lct

    题目链接 题意: 给一棵树.有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstrea ...

  6. SPOJ QTREE5 lct

    题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set ...

  7. SPOJ QTREE3 - Query on a tree again!

    You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are number ...

  8. SPOJ QTREE6 lct

    题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #inc ...

  9. 【模板时间】◆模板·II◆ 树链剖分

    [模板·II]树链剖分 学长给我讲树链剖分,然而我并没有听懂,还是自学有用……另外感谢一篇Blog +by 自为风月马前卒+ 一.算法简述 树链剖分可以将一棵普通的多叉树转为线段树计算,不但可以实现对 ...

随机推荐

  1. 洛谷——P1586 四方定理

    P1586 四方定理 题目描述 四方定理是众所周知的:任意一个正整数nn,可以分解为不超过四个整数的平方和.例如:25=1^{2}+2^{2}+2^{2}+4^{2}25=12+22+22+42,当然 ...

  2. 超级素数(sprime) (BFS)

    问题 G: 超级素数(sprime) 时间限制: 1 Sec  内存限制: 64 MB提交: 47  解决: 11[提交][状态][讨论版] 题目描述 超级素数是指一个素数,每去掉后面一个数字,总能保 ...

  3. 杂谈PID控制算法——最终篇:C语言实现51单片机中的PID算法

    真遗憾,第二篇章没能够发表到首页上去.趁热打铁.把最终篇——代码篇给发上来. 代码的设计思想请移步前两篇文章 //pid.h #ifndef __PID__ #define __PID__ /*PID ...

  4. 利用Java位运算符,完成Unsigned转换(无符号)

    方案二:利用Java位运算符,完成Unsigned转换. 正常情况下,Java提供的数据类型是有符号signed类型的,可以通过位运算的方式得到它们相对应的无符号值,参见几个方法中的代码: publi ...

  5. Java下String逗号数组和List<String>的互相转换

    说明:很遗憾,组装的时候只能遍历. 方法: public static String listToString(List<String> list){ if(list==null){ re ...

  6. Oracle数据库冷备份与恢复(救命稻草)

    说明,只要是同样系统,同样数据库版本,是可以做冷备恢复.冷备份数据必须是数据库不在open状态下.以oracle11gR2为例. 一.冷备份与冷恢复 具体步骤如下. 1. 复制旧的数据库文件 (1) ...

  7. WebForm页面使用Ajax

    AJAX:”Asynchronous JavaScript and XML” 中文意思:异步JavaScript和XML.指一种创建交互式网页应用的网页开发技术.AJAX并非缩写词,而是由Jesse ...

  8. mac上虚拟机:VMWare Fusion, VirtualBox, Parallels Desktop, CrossOver, Veertu

    作者:Louis Tong链接:https://www.zhihu.com/question/35731328/answer/66127970来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非 ...

  9. MyBatis学习-偏实践(单独MyBatis项目)

    准备先把MyBatis搞熟悉了,然后把SpringMVC搞熟悉了. MyBatis的材料,除了我之前自己实验的 http://www.cnblogs.com/charlesblc/p/5906431. ...

  10. unity backbuffer

    拿unity backbuffer的方法 var  backbuffer = new RenderTargetIdentifier(BuiltinRenderTextureType.None); 这个 ...