## 题目描述

给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白

有两种操作:

0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)

1 v : 询问1到v的路径上的第一个黑点,若无,输出-1

输入输出格式

输入格式:

第一行 N,Q,表示N个点和Q个操作

第二行到第N行N-1条无向边

再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).

输出格式:

对每个1 v操作输出结果

输入输出样例

输入样例#1: 复制

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

输出样例#1: 复制

-1

8

-1

2

-1

说明

For 1/3 of the test cases, N=5000, Q=400000.

For 1/3 of the test cases, N=10000, Q=300000.

For 1/3 of the test cases, N=100000, Q=100000.

Solution

这题显然是树链剖分,先把dfs序处理出来,但线段树存什么呢?可以发现,若以1为根,进行dfs序,这样1到每个点之间的最早出现的黑点,显然是dfs序最小值,这样线段树存最小值就行了,我们还要把线段树上的点映射回树中结点。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll(x) (x*2)
#define rr(x) (x*2+1)
using namespace std;
struct Node
{
int to,next;
}a[201001];
int len,last[200110],siz[201010],son[201100],dep[201001],fa[200010],yuan[200101];
int id[201010],cnt,n,sum[400101],top[400101],mn[400110];
void add(int a1,int a2)
{
a[++len].to=a2;
a[len].next=last[a1];
last[a1]=len;
}
void dfs1(int x,int father)
{
int mxson=-1;siz[x]=1;
for(int i=last[x];i;i=a[i].next)
{
int to=a[i].to;
if(to==father) continue;
dep[to]=dep[x]+1;
fa[to]=x;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>mxson) son[x]=to,mxson=siz[to];
}
}
void dfs2(int x,int topf)
{
id[x]=++cnt;
yuan[cnt]=x;
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=last[x];i;i=a[i].next)
{
int to=a[i].to;
if(to==fa[x]||to==son[x]) continue;
dfs2(to,to);
}
}
void pushup(int node){mn[node]=min(mn[ll(node)],mn[rr(node)]);}
void gai(int node,int l,int r,int pos)
{
if(l==r) {sum[node]^=1;if(sum[node]==1) mn[node]=l;else mn[node]=1e9;return;}
int mid=(l+r)/2;
if(pos<=mid) gai(ll(node),l,mid,pos);
else gai(rr(node),mid+1,r,pos);
pushup(node);
}
int cha(int node,int l,int r,int left,int right)
{
if(l>=left&&r<=right) return mn[node];
int mid=(l+r)/2,ans=1e9;
if(left<=mid) ans=min(ans,cha(ll(node),l,mid,left,right));
if(right>mid) ans=min(ans,cha(rr(node),mid+1,r,left,right));
return ans;
}
int cha1(int x,int y)
{
int ans=1e9;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=min(ans,cha(1,1,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=min(ans,cha(1,1,n,id[x],id[y]));
if(ans==1e9)
return -1;
return yuan[ans];
}
int main()
{
for(int i=0;i<=400000;i++)
mn[i]=1e9;
int q,x,y,opt;
cin>>n>>q;
for(int i=1;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
dep[1]=1;
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&opt,&x);
if(opt==0)
gai(1,1,n,id[x]);
else
printf("%d\n",cha1(1,x));
}
}

博主蒟蒻,可以随意转载,但必须附上原文链接k-z-j

Qtree3的更多相关文章

  1. [题解]luogu P4116 Qtree3

    终于来到了Qtree3, 其实这是Qtree系列中最简单的一道题,并不需要线段树, 只要树链剖分的一点思想就吼了. 对于树链剖分剖出来的每一根重链,在重链上维护一个Set就好了, 每一个Set里存的都 ...

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

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

  3. 树链剖分&咕咕咕了好久好久的qtree3

    前言 显然qtree系列都是树链剖分辣 发现自己没有专门整理过树链剖分耶 辣么就把这篇博客魔改成树链剖分好辣(貌似除了树剖也没什么好写的) 正文 废话了辣么多终于开始了 一.树剖怎么写鸭 二.树剖有什 ...

  4. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  5. Qtree3题解(树链剖分(伪)+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...

  6. P4116 Qtree3

    思路 可以树剖可以LCT,树剖就是每个重链开一个SET维护一下黑点的深度 非常不优美 使用LCT,在splay上二分找出需要的节点即可 代码 #include <cstdio> #incl ...

  7. Qtree3题解(树链剖分+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意 很易懂吧.. 题解 我的做法十分的暴力:树链剖分(伪)+线段树+ std :: set ...

  8. 洛谷 P4116 Qtree3

    Qtree系列第三题 我是题面 读完题大概不难判断是一道树剖的题 这道题的关键是记录两种状态,以及黑点的序号(不是编号) 线段树啊当然 定义两个变量v,f,v表示距离根节点最近的黑点,默认-1,f则表 ...

  9. 【洛谷 P4116】 Qtree3 (树链剖分)

    题目链接 树剖练手题,想复习下树剖. 第一次提交\(T\)成QQC 看我 ??? 看了数据范围的确挺恶心的,我的复杂度是\(O(Mlog^2N)\)的,数据范围有三段 For 1/3 of the t ...

  10. 树链剖分【p4116】Qtree3 - Query on a tree

    Description 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑 ...

随机推荐

  1. SQL Server 内置函数实现MD5加密

    一.MD5加密 HASHBYTES ('加密方式', '待加密的值')     加密方式= MD2 | MD4 | MD5 | SHA | SHA1     返回值类型:varbinary(maxim ...

  2. 牛客网 牛客练习赛11 A.假的线段树

    看不懂题意,而且太菜,写了两道就溜了... A.假的线段树 链接:https://www.nowcoder.com/acm/contest/59/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2 ...

  3. k8s入门简介

    1.docker的三种编排工具 Docker的第一类编排工具: a.docker compose(docker原生):只能对一个主机上的容器进行编排,无法编排多个主机上的容器; b.docker sw ...

  4. free如何知道释放内存长度:vs与glibc分配内存时编译器内部处理

    鉴于网上这个资料实在太少,将以前整理过却未完全的一篇文章贴出来,希望大牛指正vs下内存管理方式.可联系gaoshiqiang1987@163.com vs分配内存 vs没有源码,编译器在分配内存时,分 ...

  5. 投影纹理映射(Projective Texture Mapping) 【转】

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”  投影纹理映射( Projective ...

  6. 安装odoo 9实录

    安装Ubuntu,省略 下载 odoo源码 使用 git 下载源码 mkdir /opt/openerp/server cd /opt/openerp/server git clone https:/ ...

  7. javascript 高级编程系列 - 继承

    1. 原型链继承 (缺点:子类继承父类的引用类型的属性值会在各个实例中共享,创建子类实例时无法向父类构造函数传递参数) // 定义父类构造函数 function SuperClass(father, ...

  8. Spring Cloud(十一):Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

    上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制,但其实Zuul还有更多的应用场景,比如:鉴权.流量转发.请求统计等等,这些功能都可以使用Zuul来实现. Zuul的核心 Filter是Zuu ...

  9. php跳转

    header("Location: http://bbs. lampbrother.net"); header("refresh:0;url=./login.php&qu ...

  10. ORACLE 36进制和10进制,互相转换函数

    第一部分 --36转10进制 create or replace function f_36to10 (str varchar) return int  is returnValue int;   s ...