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

    https://www.lydsy.com/JudgeOnline/problem.php?id=1095

    动态点分治

    其实就是做点分治时把当前找出来的重心向上一次找到的重心连边,

    这样可以是重构后的树高为log的。

    重构后的数称为点分树。

    构造出点分树,

    每个节点开两个堆分别维护子树到它的所有链和他的子树到父分治节点的所有链。

    再开一个全局堆维护每个节点的最大答案。

    老年选手表示已经码不动数据结构,debug 2hours,QWQ。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    #define re register
    #define rep(i,s,t) for(register int i=s;i<=t;++i)
    #define _rep(i,s,t) for(register int i=s;i>=t;--i)
    #define Rep(i,s,t) for(register int i=s;i<t;++i)
    #define go(x) for(register int e=las[x];e;e=nxt[e])
    using namespace std;
    namespace IO{
        #define gc getchar()
        #define pc(x) putchar(x)
        template<typename T>inline void read(T &x){
            x=0;int f=1;char ch=gc;while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;}
            while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc;x*=f;return;
        }
        template<typename T>inline void write(T x=0){
            T wr[51];wr[0]=0;if(x<0)pc('-'),x=-x;if(!x)pc(48);
            while(x)wr[++wr[0]]=x%10,x/=10;while(wr[0])pc(48+wr[wr[0]--]);return;
        }
    }
    using IO::read;
    using IO::write;
    #define gi(x) read(x)
    #define gii(x,y) read(x),read(y)
    #define giii(x,y,z) read(x),read(y),read(z)
    const int N=2e5+11,inf=1<<30;
    int n,m,tot,x,y,sum,rt;
    int nxt[N],las[N],to[N],up[N][18],dep[N];
    int sz[N],mx[N],fa[N];
    bool vis[N],light[N];
    struct heap{
        priority_queue<int>A,B;
        inline void push(int x){
            A.push(x);
        }
        inline void erase(int x){
            B.push(x);
        }
        inline int top(){
            for(;B.size()&&A.top()==B.top();)
                A.pop(),B.pop();
            if(A.size())
                return A.top();
            return 0;
        }
        inline void pop(){
            for(;B.size()&&A.top()==B.top();)
                A.pop(),B.pop();
            if(A.size())
                A.pop();
        }
        inline int sec(){
            re int tmp=top();
                pop();
            re int ret=top();
                push(tmp);
            return ret;
        }
        inline int size(){
            return A.size()-B.size();
        }
    }c[N>>1],f[N>>1],ans;
    inline void ins(heap &s){
        //if(s.size()>1)
        //    printf("ins:%d %d
    ",s.top(),s.sec());
        if(s.size()>1)
            ans.push(s.top()+s.sec());
    }
    inline void del(heap &s){
        //if(s.size()>1)
        //    printf("del:%d %d
    ",s.top(),s.sec());
        if(s.size()>1)
            ans.erase(s.top()+s.sec());
    }
    inline void add(int x,int y){
        nxt[++tot]=las[x],las[x]=tot,to[tot]=y;
    }
    inline void dfs(int x,int anc){
        up[x][0]=anc;
        rep(i,1,17)
            up[x][i]=up[up[x][i-1]][i-1];
        go(x){
            if(to[e]==anc)continue;
            dep[to[e]]=dep[x]+1;
            dfs(to[e],x);
        }
    }
    inline int lca(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        int t=dep[x]-dep[y];
        _rep(i,17,0)
            if(t>>i&1)
                x=up[x][i];
        if(x==y)
            return x;
        _rep(i,17,0)
            if(up[x][i]!=up[y][i])
                x=up[x][i],y=up[y][i];
        return up[x][0];
    }
    inline int dis(int x,int y){
        return dep[x]+dep[y]-2*dep[lca(x,y)];
    }
    inline void findrt(int x,int anc){
        sz[x]=1,mx[x]=0;
        go(x){
            if(vis[to[e]]||to[e]==anc)continue;
            findrt(to[e],x);
            sz[x]+=sz[to[e]];
            mx[x]=max(mx[x],sz[to[e]]);
        }
        mx[x]=max(mx[x],sum-sz[x]);
        if(mx[x]<mx[rt])
            rt=x;
    }
    inline void work(int x,int anc,int R){
        //printf("%d %d %d
    ",x,anc,R);
        f[rt].push(dis(x,R));
        go(x){
            if(to[e]==anc||vis[to[e]])continue;
            work(to[e],x,R);
        }
    }
    inline void build_tree(int x,int anc){
        fa[x]=anc,vis[x]=1,c[x].push(0),work(x,0,anc);
        //printf("%d %d
    ",x,anc);
        int v;
        go(x){
            if(vis[to[e]])continue;
            rt=0,mx[0]=inf,sum=sz[to[e]],
            findrt(to[e],x),v=rt,build_tree(rt,x);
            c[x].push(f[v].top());
        }
        ins(c[x]);
    }
    inline void on(int x){
        del(c[x]),c[x].erase(0),ins(c[x]);
        for(re int i=x;i;i=fa[i]){
            del(c[fa[i]]);
            if(f[i].size())
                c[fa[i]].erase(f[i].top());
            f[i].erase(dis(x,fa[i]));
            if(f[i].size())
                c[fa[i]].push(f[i].top());
            ins(c[fa[i]]);
        }
    }
    inline void off(int x){
        del(c[x]),c[x].push(0),ins(c[x]);
        for(re int i=x;i;i=fa[i]){
            del(c[fa[i]]);
            if(f[i].size())
                c[fa[i]].erase(f[i].top());
            f[i].push(dis(x,fa[i]));
            if(f[i].size())
                c[fa[i]].push(f[i].top());
            ins(c[fa[i]]);
        }
    }
    int main(){
        gi(n);
        rep(i,2,n){
            gii(x,y);
            add(x,y),add(y,x);
        }
        dfs(1,0),mx[0]=inf,rt=0,sum=n,
        findrt(1,0),build_tree(rt,0);
        int num=n,q;char ch[10];
        gi(q);
        for(;q--;){
            scanf("%s",ch);
            if(ch[0]=='C'){
                gi(x);
                if(light[x])
                    off(x),++num;
                else
                    on(x),--num;
                light[x]^=1;
            }
            else
                printf("%d
    ",num<=1?num-1:ans.top());
        }
        return 0;
    }
    code
  • 相关阅读:
    如何基于日志,同步实现数据的一致性和实时抽取?
    实例解说AngularJS在自动化测试中的应用
    漏洞管理平台『洞察』部署指南
    UAVStack的慢SQL数据库监控功能及其实现
    淡说Linux 的发展史
    一张图告诉你E-R图怎么画
    一张图告诉你UML图怎么画❀
    最简单,最明了,看了就会的VScode和C++的配置!(Visual Studio Code)
    用Eclipse开发项目,你不能不知道的快捷键
    什么年代了,你还不会用油猴刷网课!
  • 原文地址:https://www.cnblogs.com/Stump/p/9218105.html
Copyright © 2011-2022 走看看