考虑整体二分,假设二分到区间$[l,r]$,即要对若干个询问,判断这些询问的答案与$mid=lfloorfrac{l+r}{2} floor$的关系
根据题意,答案$le mid$等价于重要度$>mid$的请求都经过$x$($x$为询问的节点)
同时,这些询问的答案一定在$[l,r]$中,即重要度$>r$的请求都经过$x$,因此在这里只需要判定$(mid,r]$中的请求是否都经过$x$即可,显然是可以维护的
(关于判定是否都经过$x$,等价于请求总数等于经过$x$的请求数,后者用线段树+差分维护即可)
时间复杂度为$o(nlog^{2}n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct edge{ 8 int nex,to; 9 }edge[N<<1]; 10 struct Data{ 11 int p,x,y,z,lca; 12 }q[N<<1]; 13 vector<Data>vl,vr; 14 int E,n,m,mq,x,y,head[N],dfn[N],sz[N],dep[N],fa[N][21],ans[N<<1],f[N<<2]; 15 void add(int x,int y){ 16 edge[E].nex=head[x]; 17 edge[E].to=y; 18 head[x]=E++; 19 } 20 int lca(int x,int y){ 21 if (dep[x]<dep[y])swap(x,y); 22 for(int i=20;i>=0;i--) 23 if (dep[fa[x][i]]>=dep[y])x=fa[x][i]; 24 if (x==y)return x; 25 for(int i=20;i>=0;i--) 26 if (fa[x][i]!=fa[y][i]){ 27 x=fa[x][i]; 28 y=fa[y][i]; 29 } 30 return fa[x][0]; 31 } 32 void dfs(int k,int f,int s){ 33 dfn[k]=++dfn[0]; 34 sz[k]=1; 35 dep[k]=s; 36 fa[k][0]=f; 37 for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1]; 38 for(int i=head[k];i!=-1;i=edge[i].nex) 39 if (edge[i].to!=f){ 40 dfs(edge[i].to,k,s+1); 41 sz[k]+=sz[edge[i].to]; 42 } 43 } 44 void update(int k,int l,int r,int x,int y){ 45 f[k]+=y; 46 if (l==r)return; 47 if (x<=mid)update(L,l,mid,x,y); 48 else update(R,mid+1,r,x,y); 49 } 50 int query(int k,int l,int r,int x,int y){ 51 if ((l>y)||(x>r))return 0; 52 if ((x<=l)&&(r<=y))return f[k]; 53 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 54 } 55 void calc(int x,int y,int l,int r){ 56 if (x>y)return; 57 if (l==r){ 58 for(int i=x;i<=y;i++) 59 if (q[i].p==2)ans[q[i].y]=l; 60 return; 61 } 62 int s=0; 63 vl.clear(),vr.clear(); 64 for(int i=x;i<=y;i++){ 65 if (q[i].p==2){ 66 int ss=query(1,1,n,dfn[q[i].x],dfn[q[i].x]+sz[q[i].x]-1); 67 if (s==ss)vl.push_back(q[i]); 68 else vr.push_back(q[i]); 69 } 70 else{ 71 if (q[i].z<=mid){ 72 vl.push_back(q[i]); 73 continue; 74 } 75 vr.push_back(q[i]); 76 int ss=1; 77 if (q[i].p)ss=-1; 78 s+=ss; 79 update(1,1,n,dfn[q[i].x],ss); 80 update(1,1,n,dfn[q[i].y],ss); 81 update(1,1,n,dfn[q[i].lca],-ss); 82 if (q[i].lca!=1)update(1,1,n,dfn[fa[q[i].lca][0]],-ss); 83 } 84 } 85 for(int i=0;i<vl.size();i++)q[x+i]=vl[i]; 86 for(int i=0;i<vr.size();i++)q[x+vl.size()+i]=vr[i]; 87 for(int i=x;i<=y;i++){ 88 if ((q[i].p==2)||(q[i].z<=mid))continue; 89 int ss=1; 90 if (q[i].p)ss=-1; 91 update(1,1,n,dfn[q[i].x],-ss); 92 update(1,1,n,dfn[q[i].y],-ss); 93 update(1,1,n,dfn[q[i].lca],ss); 94 if (q[i].lca!=1)update(1,1,n,dfn[fa[q[i].lca][0]],ss); 95 } 96 int xx=x+vl.size(); 97 calc(x,xx-1,l,mid); 98 calc(xx,y,mid+1,r); 99 } 100 int main(){ 101 scanf("%d%d",&n,&m); 102 memset(head,-1,sizeof(head)); 103 for(int i=1;i<n;i++){ 104 scanf("%d%d",&x,&y); 105 add(x,y); 106 add(y,x); 107 } 108 dfs(1,1,0); 109 for(int i=1;i<=m;i++){ 110 scanf("%d",&q[i].p); 111 if (q[i].p==0){ 112 scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z); 113 q[i].lca=lca(q[i].x,q[i].y); 114 } 115 if (q[i].p==1){ 116 scanf("%d",&x); 117 q[i].x=q[x].x,q[i].y=q[x].y,q[i].z=q[x].z,q[i].lca=q[x].lca; 118 } 119 if (q[i].p==2){ 120 scanf("%d",&q[i].x); 121 q[i].y=++mq; 122 } 123 } 124 calc(1,m,0,1e9); 125 for(int i=1;i<=mq;i++){ 126 if (!ans[i])ans[i]=-1; 127 printf("%d ",ans[i]); 128 } 129 }
(另外洛谷上的第一篇题解查询复杂度是$o(nlog n)$,但修改似乎是$o(nlog^{2}n)$的)