P4116 Qtree3
题目描述
给出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.
//记录每个点下面那段区间的黑色的深度最浅的点是谁 //修改到叶子节点,直接修改,pushup的时候在左右儿子里取个最优的 //两天没做有些生疏了 //update的时候位置直接传的v,应该是node[v].s, //因为找的是v这个点在线段树中的位置 //还要传一下v等于几 //node[v].s是在线段树中的位置,v是要改的节点的标号 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=1e5+5; int n,m; int head[N],num_edge; struct Edge { int v,nxt; }edge[N<<1]; struct NODE { int fa,son; int size,dep; int top; int s,t; }node[N]; struct TREE { TREE *lson,*rson; int l,r,mid; int num,col; }tree[N<<2]; typedef TREE* Tree; Tree Root,now_node=tree; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } inline void add_edge(int u,int v) { edge[++num_edge].v=v; edge[num_edge].nxt=head[u]; head[u]=num_edge; } void dfs1(int u) { node[u].size=1; for(int i=head[u],v;i;i=edge[i].nxt) { v=edge[i].v; if(v==node[u].fa) continue; node[v].fa=u; node[v].dep=node[u].dep+1; dfs1(v); node[u].size+=node[v].size; if(node[v].size>node[node[u].son].size) node[u].son=v; } } int bound; void dfs2(int u,int top) { node[u].s=++bound; node[u].top=top; if(node[u].son) { dfs2(node[u].son,top); for(int i=head[u],v;i;i=edge[i].nxt) { v=edge[i].v; if(v==node[u].son||v==node[u].fa) continue; dfs2(v,v); } } node[u].t=bound; } void build(Tree &root,int l,int r) { root=++now_node; root->l=l,root->r=r,root->mid=l+r>>1; if(l==r) return; build(root->lson,l,root->mid); build(root->rson,root->mid+1,r); } void better(Tree root) { if(node[root->lson->num].dep>node[root->rson->num].dep) root->num=root->rson->num; else root->num=root->lson->num; } void update(const Tree &root,int pos,int num) { if(root->l==root->r) { root->col^=1; if(root->col) root->num=num; else root->num=0; return; } if(pos<=root->mid) update(root->lson,pos,num); else update(root->rson,pos,num); better(root); } int query(const Tree &root,int l,int r) { if(root->l==l&&root->r==r) return root->num; if(r<=root->mid) return query(root->lson,l,r); else if(l>root->mid) return query(root->rson,l,r); else { int a=query(root->lson,l,root->mid),b=query(root->rson,root->mid+1,r); return node[a].dep>node[b].dep?b:a; } } inline int Query(int x,int y) { int fx=node[x].top,fy=node[y].top; int ans=0,tmp,dep=599518803; while(fx!=fy) { if(node[fx].dep>node[fy].dep) { tmp=query(Root,node[fx].s,node[x].s); if(dep>node[tmp].dep) ans=tmp,dep=node[tmp].dep; x=node[fx].fa; fx=node[x].top; } else { tmp=query(Root,node[fy].s,node[y].s); if(dep>node[tmp].dep) ans=tmp,dep=node[tmp].dep; y=node[fy].fa; fy=node[y].top; } } if(node[x].dep>node[y].dep) { tmp=query(Root,node[y].s,node[x].s); if(dep>node[tmp].dep) ans=tmp; } else { tmp=query(Root,node[x].s,node[y].s); if(dep>node[tmp].dep) ans=tmp; } return ans?ans:-1; } int u,v; int main() { node[0].dep=0x7fffffff; n=read(),m=read(); for(int i=1;i<n;++i) { u=read(),v=read(); add_edge(u,v); add_edge(v,u); } dfs1(1); dfs2(1,1); build(Root,1,n); int opt,v; for(int i=1;i<=m;++i) { opt=read(),v=read(); if(opt==0) update(Root,node[v].s,v); else { printf("%d\n",Query(1,v)); } } return 0; }