zoukankan      html  css  js  c++  java
  • BZOJ 2243 染色

    树链剖分+区间染色

    因为是一颗树不是森林,所以应该用树剖就行,但是LCT好像也能写。。
    直接用线段树维护树上的节点,注意pushdown还有询问的时候要考虑区间相交的地方,也就是左孩子右边和有孩子的左边,如果两个颜色相同就-1
    树上询问的时候也是一样,跨越轻链的时候也要看一下相接的地方颜色是不是一样。。w

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    
    const int N = 100005;
    int n, m, cnt, dfn, head[N], size[N], depth[N], p[N], son[N], top[N], val[N], w[N], id[N];
    int tree[N<<2], lc[N<<2], rc[N<<2], c[N<<2];
    struct Edge { int v, next; } edge[N<<1];
    
    void addEdge(int a, int b){
        edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
    }
    
    void dfs1(int s, int fa){
        depth[s] = depth[fa] + 1;
        p[s] = fa;
        size[s] = 1;
        int child = -1;
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(u == fa) continue;
            dfs1(u, s);
            size[s] += size[u];
            if(size[u] > child) child = size[u], son[s] = u;
        }
    }
    
    void dfs2(int s, int tp){
        id[s] = ++dfn;
        w[id[s]] = val[s];
        top[s] = tp;
        if(son[s] != -1) dfs2(son[s], tp);
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(u == p[s] || u == son[s]) continue;
            dfs2(u, u);
        }
    }
    
    void push_up(int rt){
        int l = rt << 1, r = rt << 1 | 1;
        tree[rt] = tree[l] + tree[r];
        lc[rt] = lc[l], rc[rt] = rc[r];
        if(rc[l] == lc[r]) tree[rt] --;
    }
    
    void push_down(int rt){
        //printf("c[%d] = %d
    ", rt, c[rt]);
        if(c[rt] != -1){
            int ls = rt << 1, rs = rt << 1 | 1;
            c[ls] = c[rs] = c[rt];
            tree[ls] = tree[rs] = 1;
            lc[ls] = rc[ls] = lc[rs] = rc[rs] = c[rt];
            c[rt] = -1;
        }
    }
    
    void buildTree(int rt, int l, int r){
        if(l == r){
            tree[rt] = 1, c[rt] = -1, lc[rt] = rc[rt] = w[l];
            return;
        }
        int mid = (l + r) >> 1;
        buildTree(rt << 1, l, mid);
        buildTree(rt << 1 | 1, mid + 1, r);
        push_up(rt);
    }
    
    void modify(int rt, int l, int r, int ml ,int mr, int tot){
        if(l == ml && r == mr){
            c[rt] = tot, tree[rt] = 1, lc[rt] = rc[rt] = tot;
            return;
        }
        push_down(rt);
        int mid = (l + r) >> 1;
        if(ml > mid) modify(rt << 1 | 1, mid + 1, r, ml, mr, tot);
        else if(mr <= mid) modify(rt << 1, l, mid, ml, mr, tot);
        else modify(rt << 1, l, mid, ml, mid, tot), modify(rt << 1 | 1, mid + 1, r, mid + 1, mr, tot);
        push_up(rt);
    }
    
    int query(int rt, int l, int r, int ql, int qr){
        if(l == ql && r == qr){
            return tree[rt];
        }
        push_down(rt);
        int mid = (l + r) >> 1;
        if(ql > mid) return query(rt << 1 | 1, mid + 1, r, ql, qr);
        else if(qr <= mid) return query(rt << 1, l, mid, ql, qr);
        else{
            int ls = query(rt << 1, l, mid, ql, mid);
            int rs = query(rt << 1 | 1, mid + 1, r, mid + 1, qr);
            return rc[rt << 1] == lc[rt << 1 | 1] ? ls + rs - 1 : ls + rs;
        }
    }
    
    int color(int rt, int l, int r, int index){
        if(l == r) return lc[rt];
        push_down(rt);
        int mid = (l + r) >> 1;
        if(index > mid) return color(rt << 1 | 1, mid + 1, r, index);
        return color(rt << 1, l, mid, index);
    }
    
    void treeModify(int x, int y, int tot){
        while(top[x] != top[y]){
            if(depth[top[x]] < depth[top[y]]) swap(x, y);
            modify(1, 1, n, id[top[x]], id[x], tot);
            x = p[top[x]];
        }
        if(depth[x] > depth[y]) swap(x, y);
        modify(1, 1, n, id[x], id[y], tot);
    }
    
    int treeQuery(int x, int y){
        int ret = 0;
        while(top[x] != top[y]){
            if(depth[top[x]] < depth[top[y]]) swap(x, y);
            ret += query(1, 1, n, id[top[x]], id[x]);
            if(color(1, 1, n, id[top[x]]) == color(1, 1, n, id[p[top[x]]])) ret --;
            x = p[top[x]];
        }
        if(depth[x] > depth[y]) swap(x, y);
        ret += query(1, 1, n, id[x], id[y]);
        return ret;
    }
    
    int main(){
    
        full(head, -1), full(son, -1), full(c, -1);
        n = read(), m = read();
        for(int i = 1; i <= n; i ++) val[i] = read();
        for(int i = 0; i < n - 1; i ++){
            int u = read(), v = read();
            addEdge(u, v), addEdge(v, u);
        }
        dfs1(1, 0), dfs2(1, 1);
        buildTree(1, 1, n);
        while(m --){
            char opt[10]; scanf("%s", opt);
            int a = read(), b = read();
            if(opt[0] == 'C'){
                int c = read();
                treeModify(a, b, c);
            }
            else if(opt[0] == 'Q'){
                printf("%d
    ", treeQuery(a, b));
            }
        }
        return 0;
    }
    

    于是我换了个LCT的做法
    交换区间的时候注意把lc和rc也换下,其他的没啥区别。
    但是我在link的时候加了个pushup,然后莫名WA。。难道不能加的吗qwq,就算左右子树为0,pushup也不会改变什么啊。。。

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 100005;
    int n, m, tot, ch[N][2], c[N], lc[N], rc[N], val[N], rev[N], sum[N], fa[N], st[N];
    
    void newNode(int v){
        ++tot, c[tot] = -1, lc[tot] = rc[tot] = val[tot] = v;
        sum[tot] = 1, rev[tot] = ch[tot][0] = ch[tot][1] = fa[tot] = 0;
    }
    
    void reverse(int x){
        rev[x] ^= 1;
        swap(ch[x][0], ch[x][1]);
        swap(lc[x], rc[x]);
    }
    
    void pushtag(int x, int e){
        val[x] = lc[x] = rc[x] = e;
        sum[x] = 1, c[x] = e;
    }
    
    void push_up(int x){
        int l = ch[x][0], r = ch[x][1];
        lc[x] = l ? lc[l] : val[x];
        rc[x] = r ? rc[r] : val[x];
        if(l && r) sum[x] = sum[l] + sum[r] + 1 - (rc[l] == val[x]) - (lc[r] == val[x]);
        else if(l) sum[x] = sum[l] + 1 - (rc[l] == val[x]);
        else if(r) sum[x] = sum[r] + 1 - (lc[r] == val[x]);
        else sum[x] = 1;
    }
    
    void push_down(int x){
        if(rev[x]){
            int l = ch[x][0], r = ch[x][1];
            if(l) reverse(l);
            if(r) reverse(r);
            rev[x] ^= 1;
        }
        if(c[x] != -1){
            int l = ch[x][0], r = ch[x][1];
            if(l) pushtag(l, c[x]);
            if(r) pushtag(r, c[x]);
            c[x] = -1;
        }
    }
    
    bool isRoot(int x){
        return (ch[fa[x]][0] != x && ch[fa[x]][1] != x);
    }
    
    void rotate(int x){
        int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
        push_down(y), push_down(x);
        ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
        if(!isRoot(y)) ch[z][ch[z][1] == y] = x;
        fa[x] = z, fa[y] = x, ch[x][p] = y;
        push_up(y), push_up(x);
    }
    
    void splay(int x){
        int pos = 0; st[++pos] = x;
        for(int i = x; !isRoot(i); i = fa[i]) st[++pos] = fa[i];
        while(pos) push_down(st[pos--]);
        while(!isRoot(x)){
            int y = fa[x], z = fa[y];
            if(!isRoot(y)){
                (ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);
            }
            rotate(x);
        }
        push_up(x);
    }
    
    void access(int x){
        for(int p = 0; x; p = x, x = fa[x])
            splay(x), ch[x][1] = p, push_up(x);
    }
    
    void makeRoot(int x){
        access(x), splay(x), reverse(x);
    }
    
    void link(int x, int y){
        makeRoot(x), fa[x] = y;//push_up(y);
    }
    
    void split(int x, int y){
        makeRoot(x), access(y), splay(y);
    }
    
    int main(){
    
        full(c, -1);
        n = read(), m = read();
        for(int i = 1; i <= n; i ++){
            int v = read();
            newNode(v);
        }
        for(int i = 0; i < n - 1; i ++){
            int u = read(), v = read();
            link(u, v);
        }
        while(m --){
            char opt[10]; scanf("%s", opt);
            int a = read(), b = read();
            if(opt[0] == 'C'){
                int i = read();
                split(a, b);
                pushtag(b, i);
            }
            else if(opt[0] == 'Q'){
                split(a, b);
                printf("%d
    ", sum[b]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    文本转换成音频流
    把文本以图片的形式保存
    list集合绑定在datagridview上时如何实现排序
    厘米转换成像素
    sql经典语句收集
    存储过程加密
    跨服务器sql操作
    lvs(+keepalived)、haproxy(+heartbeat)、nginx 负载均衡的比较分析
    [Big Data]Hadoop详解一
    CDN技术详解及实现原理
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10712150.html
Copyright © 2011-2022 走看看