zoukankan      html  css  js  c++  java
  • Qtree4——动态点分治

    题目描述

    给出一棵边带权的节点数量为n的树,初始树上所有节点都是白色。有两种操作:

    C x,改变节点x的颜色,即白变黑,黑变白

    A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0)。

    N (N <= 100000) Q <= 200000

    时限1s

    题解

    如果没有修改的话,直接点分治,记录子树最深的白点即可。

    但是有修改。

    发现,点分治的递归层数是O(logn)的

    而且这个递归的联通块的根形成一个树形结构。不妨叫点分树。

    我们的答案是在所有递归出来的块里ans取max

    发现,每次改变一个点的颜色,会影响自己的联通块,以及点分树上这个点的所有father的答案。

    树高logn

    所以,我们考虑暴力修改每一层的答案。

    用三个堆来维护。

    一个堆h0,维护这个点P所代表的点分树的联通块中所有点到点分树上P的father的距离(树上实际距离)。

    (好处是,修改的时候,直接自底向上,父亲只要一个,这样不需要在上层再考虑哪个子树变了)

    另一个堆h1,维护这个点P的所有儿子的堆顶的值。

    我们从一个点P的h1堆里面,找到最大的和次大的,做和就是这一层的最大答案。

    如果P是白点,那么答案可以只要最大的。而且ans最少是0

    第三个堆,维护所有点代表的联通块的ans。最终答案就在这里。

    然后,所有的修改,都是删除之后再插入。

    堆的删除,用懒惰堆即可。

    代码:

    (实现细节较多:例如堆的empty判断)

    (堆中不用记录答案出自哪里,随便删除一个,剩下那个就是没有删除的。是没有区别的。直接int的堆即可)

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    il void prin(int x){
        if(x/10) prin(x/10);
        putchar(x%10+'0');
    }
    namespace Miracle{
    const int N=100000+5;
    const int inf=0x3f3f3f3f;
    int n,m;
    struct node{
        int nxt,to;
        int val;
    }e[2*N];
    int hd[N],cnt;
    il void add(int x,int y,int z){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        e[cnt].val=z;
        hd[x]=cnt;
    }
    int fa[N];
    int sz[N];
    int c[N];
    priority_queue<int>h[2][N],d[2][N],hh,dd;
    
    int dis[N][20];
    int dep[N];
    int nowsz;
    int rt,mxsz[N];
    int ans[N];
    bool vis[N];
    int gen;
    il void dfs1(int x,int ff,int d){
        dep[x]=d;
        sz[x]=1;
        mxsz[x]=0;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==ff) continue;
            if(vis[y]) continue;
            dfs1(y,x,d);
            sz[x]+=sz[y];
            mxsz[x]=max(mxsz[x],sz[y]);
        }
        mxsz[x]=max(mxsz[x],nowsz-sz[x]);
        if(mxsz[x]<=nowsz/2){
            rt=x;
        }
    }
    il void dfs2(int x,int ff,int d){
        sz[x]=1;
        if(d!=1) h[0][rt].push(dis[x][d-1]);
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(vis[y]) continue;
            if(y==ff) continue;
            dis[y][d]=dis[x][d]+e[i].val;
            dfs2(y,x,d);
            sz[x]+=sz[y];
        }
    }
    il void clear(int x,int k){
        if(h[k][x].empty()) return;
        while(d[k][x].size()&&h[k][x].size()&&h[k][x].top()==d[k][x].top()){
            h[k][x].pop();d[k][x].pop();
        }
    }
    il void upda(int x){
        //cout<<" updaing "<<x<<endl;
        ans[x]=-inf;
        if(c[x]==0) ans[x]=max(ans[x],0);
        clear(x,1);
        if(!h[1][x].empty()){
            //cout<<" sz "<<h[1][x].size()<<" "<<d[1][x].size()<<endl;
            int tmp=h[1][x].top();h[1][x].pop();
            //cout<<" tmp "<<tmp.id<<" "<<tmp.val<<endl;
            if(c[x]==0){
                ans[x]=max(ans[x],tmp);
            }
            clear(x,1);
            if(!h[1][x].empty()){
                ans[x]=max(ans[x],tmp+(h[1][x].top()));
            }
            h[1][x].push(tmp);
        }
    }
    il int divi(int x,int d,int ff){
        //cout<<" x d ff "<<x<<" "<<d<<" "<<ff<<endl;
        rt=0;
        dfs1(x,0,d);
        fa[rt]=ff;
        dis[rt][d]=0;
        dfs2(rt,0,d);
        
        vis[rt]=1;
        ans[rt]=-inf;
        int now=rt;
        for(reg i=hd[now];i;i=e[i].nxt){
            int y=e[i].to;
            if(vis[y]) continue;
            nowsz=sz[y];
            int son=divi(y,d+1,now);
            
            if(h[0][son].size()){
                h[1][now].push(h[0][son].top());
            }
        }
        upda(now);
        //cout<<" rt "<<now<<" : "<<ans[now]<<endl;
        hh.push(ans[now]);
        return now;
    }
    il void wrk(int x){
        int gg=x;
        int nd=dep[x];
        if(c[x]==0){
            c[x]^=1;
            while(x){
                //cout<<" xx nd "<<x<<" "<<nd<<" "<<endl;
                dd.push(ans[x]);
                clear(x,1);
                upda(x);
                hh.push(ans[x]);
                
                if(fa[x]){
                    if(h[0][x].size()) d[1][fa[x]].push(h[0][x].top());
                    d[0][x].push(dis[gg][nd-1]);
                    clear(x,0);
                    if(h[0][x].size()) h[1][fa[x]].push(h[0][x].top());
                }
                
                x=fa[x];
                --nd;
            }
        }
        else{
            c[x]^=1;
            while(x){
                dd.push(ans[x]);
                clear(x,1);
                upda(x);
                hh.push(ans[x]);
                
                if(fa[x]){
                    if(h[0][x].size()) d[1][fa[x]].push(h[0][x].top());
                    h[0][x].push(dis[gg][nd-1]);
                    clear(x,0);
                    if(h[0][x].size()) h[1][fa[x]].push(h[0][x].top());
                }
                
                x=fa[x];
                --nd;
            }
        }
    }
    int main(){
        scanf("%d",&n);int x,y,z;
        for(reg i=1;i<=n-1;++i){
            rd(x);rd(y);rd(z);
            add(x,y,z);add(y,x,z);
        }
        nowsz=n;
        gen=divi(1,1,0);
        int m;
        rd(m);
        char ch[10];
        while(m--){
            scanf("%s",ch+1);
            if(ch[1]=='A'){
                
                while(dd.size()&&hh.size()&&hh.top()==dd.top()){
                    hh.pop();dd.pop();
                }
                if(!hh.size()){
                    puts("They have disappeared.");
                }
                else{
                    int tmp=hh.top();
                    if(tmp==-inf) puts("They have disappeared.");
                    else {
                        (tmp<0)&&(tmp=-tmp,putchar('-'));
                        prin(tmp);putchar('
    ');
                    }
                }
            }else{
                rd(x);
                wrk(x);
            }
    //        cout<<" ans------- "<<endl;
    //        for(reg i=1;i<=n;++i){
    //            cout<<i<<" : "<<ans[i]<<endl;
    //        }
        }
        return 0;
    }
    
    }
    int main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/11/28 9:20:15
    */

    你也可以顺带AC[ZJOI2007]捉迷藏

  • 相关阅读:
    新浪微盘又是一个给力的产品啊,
    InfoQ: 百度数据库架构演变与设计
    列式数据库——Sybase IQ
    MapR初体验 淘宝共享数据平台 tbdata.org
    IBM正式发布新一代zEnterprise大型机(组图) 大型机,IBM,BladeCenter,美国,纽约 TechWeb News
    1TB is equal to the number of how many GB? 1PB equal to is equal to the number of TB? 1EB PB? | PCfault.com
    Cassandra vs HBase | WhyNosql
    The Hadoop Community Effect
    雅虎剥离开源软件平台 Hadoop ,与风投新建 Hortonworks 公司 品味雅虎
    RowOriented Database 、ColumnOriented Database 、KeyValue Store Database 、DocumentOriented Database
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10036123.html
Copyright © 2011-2022 走看看