博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P4116 Qtree3
阅读量:4990 次
发布时间:2019-06-12

本文共 2552 字,大约阅读时间需要 8 分钟。

题目描述

给出\(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 81 21 32 42 95 97 98 96 81 30 81 61 70 21 90 21 9

输出样例#1:

-18-12-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
#include
#include
#define maxn 100007#define ls rt<<1#define rs rt<<1|1using 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
>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]
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

转载于:https://www.cnblogs.com/grcyh/p/10201460.html

你可能感兴趣的文章
【Android自定义控件】支持多层嵌套RadioButton的RadioGroup
查看>>
Swift - 内存泄露原因(循环强引用)及解决办法
查看>>
AIDL-Android接口描述语言实现跨进程通讯
查看>>
剑指Offer - 九度1354 - 和为S的连续正数序列
查看>>
LeetCode - Anagrams
查看>>
用MFC时,如果程序崩溃,检查内存,然后注意GDI数量,在任务管理器里选项-查看列-GDI数量...
查看>>
angular(转)
查看>>
ansible简单现网配置
查看>>
数据结构C++版-树
查看>>
JavaScript学习总结--创建对象(3_原型)
查看>>
FZU 2092 收集水晶 dp+bfs
查看>>
Java学习---网页编辑器FCKeditor使用详解
查看>>
IDEA开发React环境配置
查看>>
香港两日游
查看>>
cordova 打包发布正式版 apk
查看>>
常用集合比较
查看>>
二分搜索
查看>>
感觉这周的每日都是累
查看>>
Tarjan求点双连通分量
查看>>
Tomcat项目自动部署脚本
查看>>