[loj2049]网络

考虑整体二分,假设二分到区间$[l,r]$,即要对若干个询问,判断这些询问的答案与$mid=\lfloor\frac{l+r}{2}\rfloor$的关系

根据题意,答案$\le mid$等价于重要度$>mid$的请求都经过$x$($x$为询问的节点)

同时,这些询问的答案一定在$[l,r]$中,即重要度$>r$的请求都经过$x$,因此在这里只需要判定$(mid,r]$中的请求是否都经过$x$即可,显然是可以维护的

(关于判定是否都经过$x$,等价于请求总数等于经过$x$的请求数,后者用线段树+差分维护即可)

时间复杂度为$o(n\log^{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\n",ans[i]);
128     }
129 }
View Code

(另外洛谷上的第一篇题解查询复杂度是$o(n\log n)$,但修改似乎是$o(n\log^{2}n)$的)

posted @ 2021-06-28 14:54  PYWBKTDA  阅读(36)  评论(0编辑  收藏  举报