题目描述

给出\(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\).

思路:对于操作\(1\),显然我们可以利用线段树的单点修改操作来实现,对于操作\(2\),要求求\(1\)到\(v\)的路径上的第一个黑点,那么我们可以考虑维护两点之间路径之间是黑点的点的深度最浅值,可以用树链剖分+线段树来实现。

代码:

#include<cstdio>
#include<algorithm>
#include<cctype>
#define maxn 100007
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int inf=1e9+7;
int n,m,num,top[maxn],cnt,head[maxn],d[maxn],size[maxn],id[maxn];
int minn[maxn<<2],fa[maxn],son[maxn],a[maxn],w[maxn];
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int v,nxt;
}e[maxn<<1];
inline void ct(int u, int v) {
e[++num].v=v;
e[num].nxt=head[u];
head[u]=num;
}
void dfs1(int u) {
size[u]=1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa[u]) {
d[v]=d[u]+1;
fa[v]=u;
dfs1(v);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
}
void dfs2(int u, int t) {
id[u]=++cnt;
top[u]=t;
a[cnt]=u;
if(son[u]) dfs2(son[u],t);
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
inline void pushup(int rt) {
minn[rt]=min(minn[ls],minn[rs]);
}
void build(int rt, int l, int r) {
if(l==r) {
minn[rt]=inf;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
void modify(int rt, int l, int r, int L) {
if(l==r) {
if(w[id[L]]^=1) minn[rt]=l;
else minn[rt]=inf;
return;
}
int mid=(l+r)>>1;
if(L<=mid) modify(ls,l,mid,L);
else modify(rs,mid+1,r,L);
pushup(rt);
}
int cmin(int rt, int l, int r, int L, int R) {
if(L>r||R<l) return inf;
if(L<=l&&r<=R) return minn[rt];
int mid=(l+r)>>1,ans=inf;
if(L<=mid) ans=min(ans,cmin(ls,l,mid,L,R));
if(R>mid) ans=min(ans,cmin(rs,mid+1,r,L,R));
return ans;
}
int query(int x, int y) {
int fx=top[x],fy=top[y],ans=inf;
while(fx!=fy) {
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
ans=min(ans,cmin(1,1,cnt,id[fx],id[x]));
x=fa[fx],fx=top[x];
}
if(id[x]>id[y]) swap(x,y);
ans=min(ans,cmin(1,1,cnt,id[x],id[y]));
return ans;
}
int main() {
n=qread(),m=qread();
for(int i=1,u,v;i<n;++i) {
u=qread(),v=qread();
ct(u,v);ct(v,u);
}
dfs1(1);dfs2(1,1);build(1,1,n);
for(int i=1,k,x;i<=m;++i) {
k=qread(),x=qread();
if(!k) modify(1,1,n,id[x]);
else {
int zrj=query(1,x);
if(zrj==inf) printf("-1\n");
else printf("%d\n",a[zrj]);
}
}
return 0;
}

洛谷P4116 Qtree3的更多相关文章

  1. 洛谷 P4116 Qtree3

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

  2. 洛谷P4116 Qtree3(树剖+线段树)

    传送门 LCT秒天秒地 树剖比较裸的题了 用线段树记录一下区间的最左边的黑点的编号(因为同一条链上肯定是最左边的深度最小,到根节点距离最近) 然后记得树剖的时候肯定是越后面的答案越优,因为深度越浅 / ...

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

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

  4. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  5. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  6. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  7. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  8. 洛谷P1710 地铁涨价

    P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交  讨论  题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...

  9. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

随机推荐

  1. json 文件解析与应用

    第一步:首先弄一个 json 文件   我这里成为 config.json 内容如下 { ": { , "desc":"中华人民共和国" }, &qu ...

  2. bzoj 3091: 城市旅行 LCT

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3091 题解: 首先前三个操作就是裸的LCT模板 只考虑第四个操作. 要求我们计算期望,所以我 ...

  3. iOS项目添加PCH文件

    1.单击Info.plist右键单击->New File->Other->PCH File创建PCH文件 文件名设置成:项目名-Prefix  ->点击Create,创建成功. ...

  4. Windows 7下Git SSH 创建Key的步骤

    1.首先你要安装Git工具 下载地址:https://git-scm.com/downloads 2.右键鼠标,选中 “Git Bash here”,当然你也可以在windows的 “开始”---&g ...

  5. 【转】LCS

    动态规划法 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加. 为了节 ...

  6. Poj 2017 Speed Limit(水题)

    一.Description Bill and Ted are taking a road trip. But the odometer in their car is broken, so they ...

  7. DSP基础

    CCS V5的使用 CCS安装与设置

  8. 【转】 Pro Android学习笔记(三一):Menu(2):扩展、图片、子菜单

    目录(?)[-] 菜单扩展 菜单项加入图片 子菜单 菜单扩展 如果菜单项很多,超过六个时,就会采用菜单扩展模式.在例子中我加入了10个菜单项,预计能进入菜单扩展模式,但是实际效果如右图所示.效果和li ...

  9. netty中的Channel、ChannelPipeline

    一.Channel与ChannelPipeline关系 每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline.这项关联是永久性 的:Channel 既不能附加另外一个 ...

  10. spring--设置注入VS构造注入

    1.在传统的程序设计中,调用亲自创建被调用者的实例,即由程序控制“对象之间的依赖关系”,这种方式的耦合度比较高:控制反转就是将由程序控制的“对象间的依赖关系”转交给Ioc容器来进行控制,被调用者的实例 ...