• [loj2049]网络


    考虑整体二分,假设二分到区间$[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 }
    View Code

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

  • 相关阅读:
    基于Vue.js的表格分页组件
    浅谈Vue.js
    利用js2image把代码压缩成圣诞树
    在AngularJS中的使用Highcharts图表控件
    使用Uploadify(UploadiFive)多文件上传控件遇到的坑
    iOS开源项目周报0323
    安卓开源项目周报0322
    前端开源项目周报0321
    iOS开源项目周报0316
    安卓开源项目周报0315
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14944492.html
Copyright © 2020-2023  润新知