• BZOJ1095 动态点分治(点分树)


    题意:

    操作1.修改一个点的颜色(黑白互换)

    操作2.询问所有黑色点之间最远距离

    点分树:当我们可以形如点分治一样的统计答案,即每次确定一个重心,然后计算他们子树之间的贡献和得出答案的时候

    我们可以将每个区域的重心作为其所有子树的重心的父亲,构成一颗新的树,显然这棵树的深度不会超过logn

    每次对于单点(边)更新的时候,只要对其所有的父亲更新,就只需要更新log个点,这样的数据结构就是点分树

    对于本题来说,最终的答案是在每个点作为链上一个点的时候,找每个点出发的最长链和次长链的和的最大值

    所以用一个堆A维护每个点在点分树中子树下所有的点到这个点父亲的距离

    再用一个堆B维护每个点所有儿子点的堆A的最大值,即每条链的最长的长度

    最后用一个堆C维护每个点的最长值 + 次长值的大小

    tips:

    1.树上两两之间的点的距离可以rmq + ST表预处理之后O(1)查询,注意转化成序列不是dfs序,具体看代码

    2.做一个供删除的优先队列,可以用两个优先队列A,B,一个正常用,删除操作就是把元素加入B,当AB顶部相同的时候一起弹出

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    struct heap{
        priority_queue<int>A,B;
        void push(int x){A.push(x);}
        void del(int x){B.push(x);}
        void init(){
            while(!B.empty() && A.top() == B.top()){
                A.pop(); B.pop();
            }
        }
        int top(){
            init();
            if(A.empty()) return 0;
            return A.top();
        }
        int size(){
            return A.size() - B.size();
        }
        int Maxdis(){
            if(size() < 2) return 0;
            int x = top(); A.pop();
            int y = top(); A.push(x);
            return x + y;
        }
    };
    struct Edge{
        int to,next;
    }edge[maxn << 1];
    int head[maxn],tot;
    void init(){
        for(int i = 0 ; i <= N ; i ++) head[i] = -1;
        tot = 0;
    }
    void add(int u,int v){
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int dep[maxn];
    int id[maxn],pos[maxn],cnt;
    void dfsinit(int u,int la){
        id[++cnt] = dep[u];
        pos[u] = cnt;
        for(int i = head[u]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(v == la) continue;
            dep[v] = dep[u] + 1;
            dfsinit(v,u);
            id[++cnt] = dep[u]; 
        }
    }
    const int SP = 20;
    int MIN[maxn][SP],mm[maxn];
    void initRMQ(int n,int b[]){
        for(int i = 1; i <= n ; i ++){
            for(int j = 0 ; j < SP; j ++){
                MIN[i][j] = INF;
            }
        }
        mm[0] = -1;
        for(int i = 1; i <= n; i ++){
            mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1:mm[i - 1];
            MIN[i][0] = b[i];
        }
        for(int j = 1; j <= mm[n]; j ++){
            for(int i = 1; i + (1 << j) - 1 <= n; i ++){
                MIN[i][j] = min(MIN[i][j - 1],MIN[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
    int rmq(int x,int y){
        if(x > y) swap(x,y);
        int k = mm[y - x + 1];
        return min(MIN[x][k],MIN[y - (1 << k) + 1][k]);
    }
    int getdis(int x,int y){
        return dep[x] + dep[y] - 2 * rmq(pos[x],pos[y]);
    }
    struct dtnode{
        int fa;
        heap Q,P;
        int Maxdis(){
            return Q.top();
        }
        int Maxline(){
            return P.Maxdis();
        }
    }dt[maxn];
    heap fans;
    int root,max_part,SUM;
    int size[maxn],vis[maxn];
    int dis[maxn];
    void dfs_root(int u,int la){
        size[u] = 1; int heavy = 0;
        for(int i = head[u]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(v == la || vis[v]) continue;
            dfs_root(v,u);
            heavy = max(heavy,size[v]);
            size[u] += size[v];
        }
        if(max_part > max(heavy,SUM - heavy)){
            max_part = max(heavy,SUM - heavy);
            root = u;
        }
    }
    void dfs(int u,int la){
        dis[u] = getdis(u,dt[root].fa);
        dt[root].Q.push(dis[u]);
        for(int i = head[u]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(v == la || vis[v]) continue;
            dfs(v,u);
        }
    }
    int divide(int t,int la){
        max_part = INF;
        root = t; 
        dfs_root(t,-1); 
        int now = root;
        dt[root].fa = la; dt[root].P.push(0);
        if(~la) dfs(root,-1);
        vis[root] = 1;
        for(int i = head[now]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(vis[v]) continue;
            SUM = size[v];
            v = divide(v,now);
            dt[now].P.push(dt[v].Maxdis());
        }
        if(dt[now].P.size() >= 2)fans.push(dt[now].Maxline());
        return now;
    }
    int use[maxn];
    int main(){
        Sca(N); init();
        for(int i = 1; i < N ; i ++){
            int u = read(),v = read();
            add(u,v); add(v,u);
        }
        dfsinit(1,-1); initRMQ(cnt,id);
        SUM = N; divide(1,-1);
        int num = N;
        Sca(M);
        while(M--){
            char op[3]; scanf("%s",op);
            if(op[0] == 'G'){
                if(num == 1) puts("0");
                else if(!num) puts("-1");
                else{
                    Pri(fans.top());
                }    
            }else{
                int v = read(); int tmp = v;
                if(use[v]) num++;
                else num--;
                if(dt[v].P.size() >= 2) fans.del(dt[v].Maxline());
                if(use[v]) dt[v].P.push(0);
                else dt[v].P.del(0);
                if(dt[v].P.size() >= 2) fans.push(dt[v].Maxline());
                while(~dt[tmp].fa){
                    int u = dt[tmp].fa;
                    if(dt[u].P.size() >= 2) fans.del(dt[u].Maxline());
                    if(dt[tmp].Q.size()) dt[u].P.del(dt[tmp].Maxdis());
                    int d = getdis(v,u);
                    if(use[v]) dt[tmp].Q.push(d);
                    else dt[tmp].Q.del(d);
                    if(dt[tmp].Q.size()) dt[u].P.push(dt[tmp].Maxdis());
                    if(dt[u].P.size() >= 2) fans.push(dt[u].Maxline());
                    tmp = u;
                }
                use[v] ^= 1;
            }
        }
        return 0;
    }
  • 相关阅读:
    【codevs1690】开关灯 (线段树 区间修改+区间求和 (标记))
    【codevs1191】数轴染色 (线段树 区间修改+固定区间查询)
    【机器学习】李航 统计学习方法 知识点总结
    【机器学习】生成模型 判别模型
    【机器学习】贝叶斯定理、精准推断、最大似然估计、连续特征参数估计、EM算法
    python queue 讲解
    【tensorflow】 CNN卷积神经网络原理讲解+图片识别应用(附源码)
    URL解析过程
    Python 可迭代对象迭代器生成器的区别
    【Linux】 修改主机名
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/11530003.html
Copyright © 2020-2023  润新知