首页 > 代码库 > bzoj 2243: SDOI2011 染色

bzoj 2243: SDOI2011 染色

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

    上代码:

#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>#include <cmath>#define N 100010#define inf 0x7f7f7f7fusing 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\n", ask(a, b));        }    }    return 0;}

 

bzoj 2243: SDOI2011 染色