• bzoj2243 树链剖分


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

    新学的树剖,在维护的时候线段树维护区间内颜色数量以及左右两端的颜色。统计的时候区间合并时判断中间的合并点颜色是否相等,相等则ans -1 

    在计算答案的时候不同的链上两端跳的过程中也要注意color[top[u]]和color[fa[top[u]]]是否相等,相等则ans--

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    inline int read(){int now=0;register char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);now=now*10+c-'0',c=getchar());return now;}
    #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;
    const double eps = 1e-9;
    const int maxn = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    int head[maxn],tot;
    struct Edge{
        int to,next;
    }edge[maxn * 2];
    void init(){
        for(int i = 1; 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],hson[maxn],fa[maxn],Size[maxn],color[maxn],Index[maxn],top[maxn];
    int nw[maxn];
    void dfs1(int t,int la){
        Size[t] = 1;
        hson[t] = 0; int MAX = 0;
        for(int i = head[t]; ~i; i = edge[i].next){
            int v = edge[i].to;
            if(v == la) continue;
            dep[v] = dep[t] + 1; fa[v] = t;
            dfs1(v,t);
            Size[t] += Size[v];
            if(Size[v] > MAX){
                MAX = Size[v];
                hson[t] = v;
            }
        }
    }
    int cnt = 0;
    void dfs2(int t,int la){
        top[t] = la;
        Index[t] = ++cnt;
        nw[cnt] = color[t];
        if(hson[t]) dfs2(hson[t],la);
        for(int i = head[t]; ~i; i = edge[i].next){
            int v = edge[i].to;
            if(v == hson[t] || v == fa[t]) continue;
            dfs2(v,v);
        }
    }
    //线段树
    struct Tree{
        int l,r;
        int sum;
        int lazy;
        int lc,rc;
    }tree[maxn << 2];
    void Pushup(int t){
        tree[t].sum = tree[t << 1].sum + tree[t << 1 | 1].sum;
        tree[t].lc = tree[t << 1].lc; tree[t].rc = tree[t << 1 | 1].rc;
        if(tree[t << 1].rc == tree[t << 1 | 1].lc) tree[t].sum--;
    } 
    void Build(int t,int l,int r){
        tree[t].lazy = 0;
        tree[t].l = l; tree[t].r = r;
        if(tree[t].l == tree[t].r){
            tree[t].sum = 1;
            tree[t].lc = tree[t].rc = nw[l];
            return;
        }
        int m = (l + r) >> 1;
        Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r);
        Pushup(t);
    }
    void Pushdown(int t){
        if(tree[t].lazy){
            tree[t << 1].lazy = tree[t << 1 | 1].lazy = tree[t].lazy;
            tree[t << 1].sum = tree[t << 1 | 1].sum = 1;
            tree[t << 1].lc = tree[t << 1 | 1].lc = tree[t].lazy;
            tree[t << 1].rc = tree[t << 1 | 1].rc = tree[t].lazy;
            tree[t].lazy = 0;
        }
    }
    void update(int t,int l,int r,int c){
        if(l <= tree[t].l && tree[t].r <= r){
            tree[t].lazy = c;
            tree[t].sum = 1;
            tree[t].lc = tree[t].rc = c;
            return;
        }
        Pushdown(t);
        int m = (tree[t].l + tree[t].r) >> 1;
        if(r <= m) update(t << 1,l,r,c);
        else if(l > m) update(t << 1 | 1,l,r,c);
        else{
            update(t << 1,l,m,c);
            update(t << 1 | 1,m + 1,r,c);
        }
        Pushup(t);
    }
    int query(int t,int l,int r){
        if(l <= tree[t].l && tree[t].r <= r) return tree[t].sum;
        Pushdown(t);
        int ans = 0;
        int m = (tree[t].l + tree[t].r) >> 1;
        if(r <= m) ans = query(t << 1,l,r);
        else if(l > m) ans = query(t << 1 | 1,l,r);
        else{
            ans = query(t << 1,l,m) + query(t << 1 | 1,m + 1,r);
            if(tree[t << 1].rc == tree[t << 1 | 1].lc) ans--;
        }
        Pushup(t);
        return ans;
    }
    int query(int t,int p){
        if(tree[t].sum == 1) return tree[t].lc;
        int m = (tree[t].l + tree[t].r) >> 1;
        if(p <= m) return query(t << 1,p);
        else if(p > m) return query(t << 1 | 1,p);
    }
    //树链剖分
    void update(int u,int v,int c){
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]]) swap(u,v);
            update(1,Index[top[u]],Index[u],c);
            u = fa[top[u]];
        }
        if(dep[u] > dep[v]) swap(u,v);
        update(1,Index[u],Index[v],c);
    } 
    int Query(int u,int v){
        int ans = 0;
        int la = 0;
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]]) swap(u,v);
            ans += query(1,Index[top[u]],Index[u]);
            if(query(1,Index[fa[top[u]]]) == query(1,Index[top[u]])) ans--;
            u = fa[top[u]];
        }
        if(dep[u] > dep[v]) swap(u,v);
        ans += query(1,Index[u],Index[v]);
        return ans;
    }
    int main(){
        Sca2(N,M); init();
        for(int i = 1; i <= N ; i ++) color[i] = read();;
        for(int i = 1; i < N ; i ++){
            int u = read(),v = read(); 
            add(u,v); add(v,u);
        }
        int root = N; dep[root] = 0;
        dfs1(root,-1); cnt = 0; dfs2(root,root);
        Build(1,1,N);
        while(M--){
            char op[3]; int a,b,c;
            scanf("%s",op); a = read(); b = read();
            if(op[0] == 'C'){
                c = read(); update(a,b,c);
            }else{
                Pri(Query(a,b));
            }
        }
        return 0;
    }
  • 相关阅读:
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:显示在 <abbr> 元素中的文本以小号字体展示,且可以将小写字母转换为大写字母
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定单词首字母大写
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定大写文本
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本小写
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:段落中超出屏幕部分不换行
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本对齐,段落中超出屏幕部分文字自动换行
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本右对齐
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本居中对齐
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本左对齐
    吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定小文本
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/10267532.html
Copyright © 2020-2023  润新知