给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白node
有两种操做:ios
0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)spa
1 v : 询问1到v的路径上的第一个黑点,若无,输出-1code
输入格式:blog
第一行 N,Q,表示N个点和Q个操做ci
第二行到第N行N-1条无向边get
再以后Q行,每行一个操做"0 i" 或者"1 v" (1 ≤ i, v ≤ N).string
输出格式:io
对每一个1 v操做输出结果ast
输入样例#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.
这题显然是树链剖分,先把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)); } }