zoukankan      html  css  js  c++  java
  • 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门

    据说正解是树剖套堆???然而代码看着稍微有那么一点点长……

    考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$mid$

    然后考虑怎么判断是否所有边都经过某一个点。我们可以用树状数组+树上差分来维护,把每一条边的两个端点的值加1,他们LCA的值减1,LCA父亲的值减1,那么如果这条边经过某一个点,那么这个点子树的和必定为1

    于是我们可以把所有大于mid的边都处理出来,然后判断子树的和是否等于路径条数就行了。这个可以用dfs序+树状数组维护

    然后整体二分的时候,我们还是能保证时间有序的,如果是修改,那么只有边数大于mid的修改要执行,否则直接扔到左边。询问的话,如果子树和等于大于mid的边数,就扔进左边,否则扔进右边

    然后代码里是每一次修改的时候都求一遍LCA的,所以时间复杂度是$O(n log^2n)$,如果用ST表求LCA的话应该能再减掉一个$log$

      1 //minamoto
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      5 char buf[1<<21],*p1=buf,*p2=buf;
      6 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
      7 inline int read(){
      8     #define num ch-'0'
      9     char ch;bool flag=0;int res;
     10     while(!isdigit(ch=getc()))
     11     (ch=='-')&&(flag=true);
     12     for(res=num;isdigit(ch=getc());res=res*10+num);
     13     (flag)&&(res=-res);
     14     #undef num
     15     return res;
     16 }
     17 char sr[1<<21],z[20];int K=-1,Z;
     18 inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
     19 inline void print(int x){
     20     if(K>1<<20)Ot();if(x<0)sr[++K]=45,x=-x;
     21     while(z[++Z]=x%10+48,x/=10);
     22     while(sr[++K]=z[Z],--Z);sr[++K]='
    ';
     23 }
     24 const int N=2e5+5;
     25 int head[N],Next[N],ver[N],tot;
     26 inline void add_edge(int u,int v){
     27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     28 }
     29 struct node{
     30     int op,x,t,ans;
     31     inline bool operator <(const node &b)const
     32     {return t<b.t;}
     33 }q[N],ll[N],rr[N];
     34 int n,m,num,c[N],fa[N],top[N],sz[N],son[N],ls[N],rs[N],dep[N],cnt,mx;
     35 int A[N],B[N],C[N],ans[N];
     36 inline void add(int x,int y){for(;x<=n;x+=x&-x)c[x]+=y;}
     37 inline int query(int x){
     38     int res=0;
     39     for(;x;x-=x&-x) res+=c[x];
     40     return res;
     41 }
     42 inline int query(int l,int r){return query(r)-query(l-1);}
     43 void dfs1(int u){
     44     sz[u]=1,dep[u]=dep[fa[u]]+1,ls[u]=++cnt;
     45     for(int i=head[u];i;i=Next[i]){
     46         int v=ver[i];
     47         if(v!=fa[u]){
     48             fa[v]=u,dfs1(v),sz[u]+=sz[v];
     49             if(sz[son[u]]<sz[v]) son[u]=v;
     50         }
     51     }
     52     rs[u]=cnt;
     53 }
     54 void dfs2(int u,int t){
     55     top[u]=t;
     56     if(son[u]){
     57         dfs2(son[u],t);
     58         for(int i=head[u];i;i=Next[i])
     59         if(ver[i]!=fa[u]&&ver[i]!=son[u])
     60         dfs2(ver[i],ver[i]);
     61     }
     62 }
     63 inline int LCA(int u,int v){
     64     while(top[u]!=top[v])
     65     dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
     66     return dep[u]<dep[v]?u:v;
     67 }
     68 void update(int u,int v,int x){
     69     int lca=LCA(u,v);
     70     add(ls[u],x),add(ls[v],x),add(ls[lca],-x);
     71     if(fa[lca]) add(ls[fa[lca]],-x);
     72 }
     73 void solve(int l,int r,int ql,int qr){
     74     if(l==r){for(int i=ql;i<=qr;++i) if(q[i].op==2) q[i].ans=l;return;}
     75     int mid=(l+r)>>1,path=0,cl=0,cr=0;
     76     for(int i=ql;i<=qr;++i){
     77         if(q[i].op==2){
     78             if(query(ls[q[i].x],rs[q[i].x])==path) ll[++cl]=q[i];
     79             else rr[++cr]=q[i];
     80         }else{
     81             if(C[q[i].x]<=mid) ll[++cl]=q[i];
     82             else{
     83                 int x=q[i].op?-1:1;path+=x;
     84                 update(A[q[i].x],B[q[i].x],x);
     85                 rr[++cr]=q[i];
     86             }
     87         }
     88     }
     89     for(int i=1;i<=cr;++i) if(rr[i].op!=2){
     90         int x=rr[i].op?1:-1;
     91         update(A[rr[i].x],B[rr[i].x],x);
     92     }
     93     for(int i=1;i<=cl;++i) q[ql+i-1]=ll[i];
     94     for(int i=1;i<=cr;++i) q[ql+cl+i-1]=rr[i];
     95     if(cl) solve(l,mid,ql,ql+cl-1);
     96     if(cr) solve(mid+1,r,ql+cl,qr);
     97 }
     98 int main(){
     99 //    freopen("testdata.in","r",stdin);
    100     n=read(),m=read();
    101     for(int i=1,u,v;i<n;++i)
    102     u=read(),v=read(),add_edge(u,v),add_edge(v,u);
    103     dfs1(1),dfs2(1,1);
    104     for(int i=1;i<=m;++i){
    105         q[i].op=read(),q[i].t=i;
    106         if(!q[i].op){
    107             A[i]=read(),B[i]=read(),C[i]=read();
    108             q[i].x=i,cmax(mx,C[i]);
    109         }else q[i].x=read();
    110     }
    111     solve(-1,mx,1,m);
    112     sort(q+1,q+1+m);
    113     for(int i=1;i<=m;++i)
    114     if(q[i].op==2) print(q[i].ans);
    115     Ot();
    116     return 0;
    117 }
  • 相关阅读:
    Beta冲刺<7/10>
    Beta冲刺<6/10>
    Beta冲刺<5/10>
    Beta冲刺--冲刺总结
    Beta冲刺<4/10>
    实验四
    结对编程第二阶段
    实验二 结对编程第一阶段
    实验报告
    团队作业第六次——Beta冲刺
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9798479.html
Copyright © 2011-2022 走看看