BZOJ4538 : [Hnoi2016]網路

Claris發表於2016-04-18

求出這棵樹的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;
}

  

相關文章