zoukankan      html  css  js  c++  java
  • bzoj 2243: SDOI2011 染色

        最近总是在做树链剖分的题(觉得有必要学一下倍增算法=_=)。这题也是一个树链剖分。维护和找答案的时候注意区间左右端点的颜色就OK了……

        上代码:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define N 100010
    #define inf 0x7f7f7f7f
    using namespace std;
    
    struct sss
    {
        int color, lc, rc;
        int num, push;
    }t[N*4];
    int n, m, color[N], nowplace = 0;
    int fa[N], deep[N], w[N], top[N], son[N] = {0}, siz[N] = {0};
    int p[N] = {0}, v[N*2], next[N*2], bnum = 0;
    
    void build_tree(int now, int l, int r)
    {
        t[now].push = 0; t[now].num = 0;
        t[now].color = t[now].lc = t[now].rc = 0;
        if (l == r) return;
        int mid = (l+r) /2 ;
        build_tree(now*2, l, mid); build_tree(now*2+1, mid+1, r);
    }
    
    void update(int now)
    {
        t[now].num = t[now*2].num + t[now*2+1].num;
        if (t[now*2].rc == t[now*2+1].lc) t[now].num--;
        t[now].lc = t[now*2].lc; t[now].rc = t[now*2+1].rc;
        if (t[now*2].color && t[now*2+1].color == t[now*2].color)
            t[now].color = t[now*2].color;
        else t[now].color = 0;
    }
    
    void downdate(int now)
    {
        if (!t[now].push) return;
        t[now*2].push = t[now*2+1].push = 1; t[now].push = 0;
        t[now*2].color = t[now*2+1].color = t[now].color;
        t[now*2].lc = t[now*2].rc = t[now*2+1].rc = t[now*2+1].lc = t[now].color;
        t[now*2].num = t[now*2+1].num = 1;
    }
    
    int findcolor(int now, int l, int r, int place)
    {
        if (l == r) return t[now].color;
        int mid = (l+r) / 2;
        downdate(now);
        if (place <= mid) return findcolor(now*2, l, mid, place);
        else return findcolor(now*2+1, mid+1, r, place);
    }
    
    void make_tree(int now, int l, int r)
    {
        if (l == r)
        {
            t[now].color = t[now].lc = t[now].rc = 0;
            t[now].num = 0; t[now].push = 0; return;
        }
        int mid = (l+r) / 2;
        make_tree(now*2, l, mid); make_tree(now*2+1, mid+1, r);
    }
    
    void tchange(int now, int l, int r, int cl, int cr, int cnum)
    {
        if (cl <= l && r <= cr)
        {
            t[now].color = cnum; t[now].lc = t[now].rc = cnum;
            t[now].num = 1; t[now].push = 1; return;
        }
        int mid = (l+r) / 2; downdate(now);
        if (cl <= mid) tchange(now*2, l, mid, cl, cr, cnum);
        if (cr > mid) tchange(now*2+1, mid+1, r, cl, cr, cnum);
        update(now);
    }
    
    int task(int now, int l, int r, int al, int ar)
    {
        if (al <= l && r <= ar) return t[now].num;
        int mid = (l+r) / 2, ans = 0; downdate(now);
        if (al <= mid) ans += task(now*2, l, mid, al, ar);
        if (ar > mid) ans += task(now*2+1, mid+1, r, al, ar);
        if (al <= mid && ar > mid)
            if (findcolor(1, 1, n, mid) == findcolor(1, 1, n, mid+1))
                ans--;
        return ans;
    }
    
    void addbian(int x, int y)
    {
        bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;
        bnum++; next[bnum] = p[y]; p[y] = bnum; v[bnum] = x;
    }
    
    void dfs_1(int now, int fat, int nowdeep)
    {
        int k = p[now]; fa[now] = fat; deep[now] = nowdeep;
        int maxson = 0; siz[now] = 1; 
        while (k)
        {
            if (v[k] != fat)
            {
                dfs_1(v[k], now, nowdeep+1);
                siz[now] += siz[v[k]];
                if (siz[v[k]] > maxson)
                {
                    maxson = siz[v[k]];
                    son[now] = v[k];
                }
            }
            k = next[k];
        }
    }
    
    void dfs_2(int now, int fat, int nowtop)
    {
        int k = p[now]; w[now] = ++nowplace; top[now] = nowtop;
        tchange(1, 1, n, w[now], w[now], color[now]);
        if (son[now]) dfs_2(son[now], now, nowtop);
        while (k)
        {
            if (v[k] != fat && v[k] != son[now])
                dfs_2(v[k], now, v[k]);
            k = next[k];
        }
    }
    
    void change(int u, int v, int changenum)
    {
        int f1 = top[u], f2 = top[v];
        if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); }
        if (f1 == f2)
        {
            if (u == v) tchange(1, 1, n, w[u], w[u], changenum);
            else tchange(1, 1, n, min(w[u], w[v]), max(w[u], w[v]), changenum);
        }
        else
        {
            tchange(1, 1, n, w[f1], w[u], changenum);
            change(fa[f1], v, changenum);
        }
    }
    
    int ask(int u, int v)
    {
        int f1 = top[u], f2 = top[v], ans = 0;
        if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); }
        if (f1 == f2)
        {
            if (u == v) return ans+1;
            else return task(1, 1, n, min(w[u], w[v]), max(w[u], w[v]));
        }
        else
        {
            ans += task(1, 1, n, w[f1], w[u]);
            int x = findcolor(1, 1, n, w[f1]), y = findcolor(1, 1, n, w[fa[f1]]);
            if (x == y) ans --;
            ans += ask(fa[f1], v);
            return ans;
        }
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        build_tree(1, 1, n);
        for (int i = 1; i <= n; ++i)
            scanf("%d", &color[i]);
        for (int i = 1; i < n; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            addbian(x, y);
        }
        dfs_1(1, 0, 1);
        dfs_2(1, 0, 1);
        for (int i = 1; i <= m; ++i)
        {
            char s[2]; scanf("%s", s);
            if (s[0] == 'C')
            {
                int a, b, c; scanf("%d%d%d", &a, &b, &c);
                change(a, b, c);
            }
            else
            {
                int a, b; scanf("%d%d", &a, &b);
                printf("%d
    ", ask(a, b));
            }
        }
        return 0;
    }
  • 相关阅读:
    线程阶段性总结——APM,ThreadPool,Task,TaskScheduler ,CancellationTokenSource
    研究BackgroundWorker后发现:AsyncOperation和SynchronizationContext的差异真的很大!
    线程同步——优势、劣势
    APM异步编程模型的优势
    DataGridView的VirtualMode,在大容量数据加载时特别有用
    【C】——C语言的位运算的优势
    【linux】——Linux tar打包命令
    【C】用文件和链表实现学生信息管理
    【C】——回调函数的好处
    【C】strcpy()需谨慎使用;
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3947805.html
Copyright © 2011-2022 走看看