BZOJ4538 : [Hnoi2016]网络
求出这棵树的dfs序,对于一条链$u-v$,假设$st[u]\leq st[v]$,那么一条链不经过点$x$当且仅当它满足下面任意一个条件:
1.$st[v]<st[x]$
2.$st[u]>en[x]$
3.$st[x]<st[lca(u,v)]\leq en[x]$
4.$st[u]<st[x],st[v]>en[x]$
前3种情况可以通过线段树做到$O(\log n)$修改,$O(\log n)$查询。
第4种情况可以通过kd-tree做到$O(\log n)$修改,$O(\sqrt{m})$查询。
总时间复杂度$O(m\sqrt{m})$。
#include<cstdio> #include<queue> #include<algorithm> using namespace std; typedef pair<int,int>P; const int N=100010,M=200010; int n,m,i,x,y,z,op[M][4],ans[M]; int g[N],v[M],nxt[M],ed,f[N],d[N],size[N],son[N],top[N],st[N],en[N],dfn; int ex[M],val[N+M];priority_queue<P>S[N]; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} void dfs(int x){ size[x]=1; for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){ f[v[i]]=x,d[v[i]]=d[x]+1; dfs(v[i]),size[x]+=size[v[i]]; if(size[v[i]]>size[son[x]])son[x]=v[i]; } } void dfs2(int x,int y){ st[x]=++dfn;top[x]=y; if(son[x])dfs2(son[x],y); for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]); en[x]=dfn; } inline int lca(int x,int y){ for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y); return d[x]<d[y]?x:y; } inline void umax(int&a,int b){if(a<b)a=b;} inline void umin(int&a,int b){if(a>b)a=b;} inline int max(int a,int b){return a>b?a:b;} void build(int x,int a,int b){ val[x]=-1; if(a==b){ while(!S[a].empty())S[a].pop(); return; } int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b); } void ins(int x,int a,int b,int c,int p){ if(a==b){ ex[p]=1; S[a].push(P(op[p][3],p)); while(!ex[S[a].top().second])S[a].pop(); val[x]=S[a].top().first; return; } int mid=(a+b)>>1; if(c<=mid)ins(x<<1,a,mid,c,p);else ins(x<<1|1,mid+1,b,c,p); val[x]=max(val[x<<1],val[x<<1|1]); } void del(int x,int a,int b,int c,int p){ if(a==b){ ex[p]=0; while(!S[a].empty()){ if(ex[S[a].top().second])break; S[a].pop(); } val[x]=S[a].empty()?-1:S[a].top().first; return; } int mid=(a+b)>>1; if(c<=mid)del(x<<1,a,mid,c,p);else del(x<<1|1,mid+1,b,c,p); val[x]=max(val[x<<1],val[x<<1|1]); } void ask(int x,int a,int b,int c,int d,int&p){ if(c>d)return; if(c<=a&&b<=d){umax(p,val[x]);return;} int mid=(a+b)>>1; if(c<=mid)ask(x<<1,a,mid,c,d,p); if(d>mid)ask(x<<1|1,mid+1,b,c,d,p); } namespace KD{ int n,id[M],root,cmp_d,X,Y; struct node{int d[2],l,r,Max[2],Min[2],v,mv,f;}T[M]; inline bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];} inline void up(int x){ if(T[x].l){ umax(T[x].Max[0],T[T[x].l].Max[0]); umin(T[x].Min[0],T[T[x].l].Min[0]); umax(T[x].Max[1],T[T[x].l].Max[1]); umin(T[x].Min[1],T[T[x].l].Min[1]); } if(T[x].r){ umax(T[x].Max[0],T[T[x].r].Max[0]); umin(T[x].Min[0],T[T[x].r].Min[0]); umax(T[x].Max[1],T[T[x].r].Max[1]); umin(T[x].Min[1],T[T[x].r].Min[1]); } } int build(int l,int r,int D,int f){ int mid=(l+r)>>1; cmp_d=D,nth_element(T+l+1,T+mid+1,T+r+1,cmp); id[T[mid].f]=mid; T[mid].f=f; T[mid].Max[0]=T[mid].Min[0]=T[mid].d[0]; T[mid].Max[1]=T[mid].Min[1]=T[mid].d[1]; T[mid].v=T[mid].mv=-1; if(l!=mid)T[mid].l=build(l,mid-1,!D,mid); if(r!=mid)T[mid].r=build(mid+1,r,!D,mid); return up(mid),mid; } inline void change(int x,int p){ for(T[x=id[x]].v=p;x;x=T[x].f){ T[x].mv=T[x].v; if(T[x].l)umax(T[x].mv,T[T[x].l].mv); if(T[x].r)umax(T[x].mv,T[T[x].r].mv); } } void ask(int x,int&p){ if(T[x].mv<=p||T[x].Min[0]>=X||T[x].Max[1]<=Y)return; if(T[x].Max[0]<X&&T[x].Min[1]>Y){p=T[x].mv;return;} if(T[x].d[0]<X&&T[x].d[1]>Y&&p<T[x].v)p=T[x].v; if(T[x].l)ask(T[x].l,p); if(T[x].r)ask(T[x].r,p); } void solve(){ for(i=1;i<=m;i++)if(!op[i][0]){ n++; x=st[op[i][1]],y=st[op[i][2]]; if(x>y)swap(x,y); T[n].d[0]=x,T[n].d[1]=y,T[n].f=i; } root=build(1,n,0,0); for(i=1;i<=m;i++){ if(!op[i][0])change(i,op[i][3]); if(op[i][0]==1)change(op[i][1],-1); if(op[i][0]==2)X=st[op[i][1]],Y=en[op[i][1]],ask(root,ans[i]); } } } int main(){ read(n),read(m); for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x); dfs(1),dfs2(1,1); for(i=1;i<=m;i++){ read(op[i][0]),read(op[i][1]); if(!op[i][0])read(op[i][2]),read(op[i][3]); ans[i]=-1; } build(1,1,n); for(i=1;i<=m;i++){ x=op[i][1],y=op[i][2],z=op[i][3]; if(!op[i][0]){ x=st[x],y=st[y]; if(x>y)swap(x,y); ins(1,1,n,y,i); } if(op[i][0]==1){ z=x; x=st[op[z][1]],y=st[op[z][2]]; if(x>y)swap(x,y); del(1,1,n,y,z); } if(op[i][0]==2)ask(1,1,n,1,st[x]-1,ans[i]); } build(1,1,n); for(i=1;i<=m;i++){ x=op[i][1],y=op[i][2],z=op[i][3]; if(!op[i][0]){ x=st[x],y=st[y]; if(x>y)swap(x,y); ins(1,1,n,x,i); } if(op[i][0]==1){ z=x; x=st[op[z][1]],y=st[op[z][2]]; if(x>y)swap(x,y); del(1,1,n,x,z); } if(op[i][0]==2)ask(1,1,n,en[x]+1,n,ans[i]); } build(1,1,n); for(i=1;i<=m;i++){ x=op[i][1],y=op[i][2],z=op[i][3]; if(!op[i][0]){ x=st[lca(x,y)]; ins(1,1,n,x,i); } if(op[i][0]==1){ z=x; x=st[lca(op[z][1],op[z][2])]; del(1,1,n,x,z); } if(op[i][0]==2)ask(1,1,n,st[x]+1,en[x],ans[i]); } KD::solve(); for(i=1;i<=m;i++)if(op[i][0]==2)printf("%d\n",ans[i]); return 0; }