一棵结点为黑色或白色的树,初始都是白色的。有两种操作

1 将一个结点换颜色
2 询问从根到结点u路径上面的第一个黑色点,没有则输出-1
Input
In the first line there are two integers N and Q.
In the next N-1 lines describe the edges in the tree: a line with two integers a b denotes an edge
between a and b. The next Q lines contain instructions "0 i" or "1 v" (1 ≤ i, v ≤ N).
Output
For each "1 v" operation, write one integer representing its result.
Sample Input
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
Sample Output
-1
8
-1
2
-1

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;const int N=200001;
int n,m,sum,cnt,now,pre[N],f[N],nxt[N],h[N],top[N],id[N],size[N],dep[N],ans,maxx,di[N];
struct oo{int a,b,dp,now;bool v;}s[N*2-20000];
void dfs(int x)
{
size[x]=1;
for(int i=h[x];i;i=nxt[i])
{
if(pre[i]==f[x])continue;
dep[pre[i]]=dep[x]+1;
f[pre[i]]=x;
dfs(pre[i]);
size[x]+=size[pre[i]];
}
}
void dfs2(int x,int f)
{
int k=0;
id[x]=++cnt;
di[cnt]=x; //dfs序中第cnt个点是x
top[x]=f;
for(int i=h[x];i;i=nxt[i])
if(size[pre[i]]>size[k]&&dep[pre[i]]>dep[x])k=pre[i];
if(!k)return ;
dfs2(k,f);
for(int i=h[x];i;i=nxt[i])
if(dep[pre[i]]>dep[x]&&pre[i]!=k)
dfs2(pre[i],pre[i]);
}
void ins(int x,int y)
{
pre[++now]=y;
nxt[now]=h[x];
h[x]=now;
}
void build(int x,int l,int r)
{
s[x].a=l,s[x].b=r;
s[x].dp=1e9;
if(l==r)
{
return ;
}
build(x<<1,l,l+r>>1);
build(x<<1|1,(l+r>>1)+1,r);
}
void get(int x,int l,int r)
//求出线段树上[l,r]哪个点是黑色的,且深度最小
{
if(s[x].a>=l&&r>=s[x].b)
{
if(s[x].dp<maxx)
{
maxx=s[x].dp; //找出深度最小值
sum=s[x].now;//对应的点
}
return ;
}
else
{
int mid=s[x].a+s[x].b>>1;
if(l<=mid)get(x<<1,l,r);
if(r>mid)get(x<<1|1,l,r);
}
}
void qmax(int x,int y)
{
maxx=1e9,sum=-1;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
get(1,id[top[x]],id[x]);
x=f[top[x]];
}
if(id[x]>id[y])
swap(x,y);
get(1,id[x],id[y]);
if(sum==0)
sum=-1;
}
void change(int x,int l)
//x指目前在哪个树上
//l是指线段中哪个位置
{
if(s[x].a==s[x].b)
{
s[x].v^=1;
if(s[x].v) //如果染成黑色
{
s[x].dp=dep[di[l]]; //求出深度
s[x].now=di[l];
//di[l]指dfs序列中第l个点是原树上哪个点
}
else //还原成白色
s[x].dp=1e9,s[x].now=0;
return ;
}
int mid=s[x].a+s[x].b>>1;
if(l<=mid)
change(x<<1,l);
else
change(x<<1|1,l);
if(s[x<<1].dp<s[x<<1|1].dp)//求出最小的深度
{
s[x].dp=s[x<<1].dp;
s[x].now=s[x<<1].now;
}
else
{
s[x].dp=s[x<<1|1].dp;
s[x].now=s[x<<1|1].now;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
ins(x,y);
ins(y,x);
}
dfs(1);
dfs2(1,1);
build(1,1,n);
int c;
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d",&c);
if(c) //查询操作
{
scanf("%d",&b);
qmax(1,b);
printf("%d\n",sum);
}
if(!c) //将某个结点换颜色
scanf("%d",&b),change(1,id[b]);
}
}

  

 

  

Spoj 2798 Qtree3的更多相关文章

  1. SPOJ 2798 QTREE3 - Query on a tree again!

    原oj题面 Time limit 2000 ms Memory limit 1572864 kB Code length Limit 50000 B OS Linux Language limit A ...

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

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

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

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

  4. SPOJ QTREE3 lct

    题目链接 题意: 给定n个点 q个询问 以下n-1行给出树边,点有黑或白色.初始化为白色 以下q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑 ...

  5. 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 ...

  6. Query on a tree again! SPOJ - QTREE3

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

  7. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  8. SPOJ DQUERY D-query(主席树)

    题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...

  9. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

随机推荐

  1. [易学易懂系列|rustlang语言|零基础|快速入门|系列文章]

    简单易懂的rustlang入门教程. [易学易懂系列|rustlang语言|零基础|快速入门|(1)|开篇] [易学易懂系列|rustlang语言|零基础|快速入门|(2)|VCCode配置] [易学 ...

  2. Java基本的程序结构设计 字符类型

    char类型 char是2个字节,和short一样. char用单引号来表示. char可以通过数字来表示,也可以通过字母来表示,也可以通过unicode编码单元来表示,特殊字符还可以通过\+字符来表 ...

  3. SpringBoot之持久化框架

    在之前的 Spring学习之旅(十二)--持久化框架 中我们介绍了 JPA 的使用,今天我们就来了解下另一种持久化框架 Mybatis. 一.集成 Mybatis 1.1 准备工作 新建用户表 CRE ...

  4. xDSL相关

    ----------------------- --------------

  5. HDU-3081-Marriage Match 2(最大流, 二分答案, 并查集)

    链接: https://vjudge.net/problem/HDU-3081 题意: Presumably, you all have known the question of stable ma ...

  6. NOIP提高组2016总结

    前言 大翻车! 300--: day1 8:30~9:00, 照常看题,思考. 9:00~9:15, 搞定第一题,很水. 9:15~9:45, 思考第二题,我考虑用分深度来处理,想出个个玄学暴力,但刚 ...

  7. electron 编译报错

    放在中文目录下的项目,会编译的时候报错 python 安装目录不要有空格,默认目录就好

  8. 对url给后台传数据的时候特殊字符需要转义

    URL中的字符只能是ASCII字符,但是ASCII字符比较少,而URL则常常包含ASCII字符集以外的字符,如非英语字符,汉字,特殊符号等等,所以要对URL进行转换.这个过程就叫做URL编码,或者叫U ...

  9. make all age=20 makefile 传参数

    你可以直接在Make的时候,在命令行下面传入一个参数或者变量,它会覆盖掉Makefile里面的变量或者参数.比如,在你的Makefile里面定义了一个变量age. .PHONY:all AGE = a ...

  10. Shell test命令/流程控制

    Shell test命令 Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值.字符和文件三个方面的测试. 数值测试 参数,说明 -eq等于则为真 -ne不等于则为真 -gt 大于则 ...