首页 > 代码库 > BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

2243: [SDOI2011]染色

Description

 

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”3段组成:“11”、“222”和“1”

请你写一个程序依次完成这m个操作。

 

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

 

Output

对于每个询问操作,输出一行答案。

 

Sample Input

6 5

2 2 1 2 1 1

1 2

1 3

2 4

2 5

2 6

Q 3 5

C 2 1 1

Q 3 5

C 5 1 2

Q 3 5

Sample Output

3

1

2

HINT

 

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

 

题解:

  树链剖分后,在相应的标号上进行线段树操作

#include<bits/stdc++.h>using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")#define ls i<<1#define rs ls | 1#define mid ((ll+rr)>>1)#define pii pair<int,int>#define MP make_pairtypedef long long LL;const long long INF = 1e18+1LL;const double Pi = acos(-1.0);const int N = 5e5+10, M = 1e3+20, mod = 1e9+7, inf = 2e9;int dep[N],head[N],t=1,sz[N],fa[N],indexS,top[N],pos[N];struct ss{int to,next;}e[N*2];int n;void add(int u,int v){e[t].to = v;e[t].next = head[u];head[u] = t++;}void dfs(int u) {    sz[u] = 1;    dep[u] = dep[fa[u]] + 1;    for(int i = head[u]; i; i = e[i].next) {        int to = e[i].to;        if(to == fa[u]) continue;        fa[to] = u;        dfs(to);        sz[u] += sz[to];    }}void dfs(int u,int chain) {    int k = 0;    pos[u] = ++indexS;    top[u] = chain;    for(int i = head[u]; i; i = e[i].next) {        int to = e[i].to;        if(dep[to] > dep[u] && sz[to] > sz[k])            k = to;    }    if(k == 0) return ;    dfs(k,chain);    for(int i = head[u]; i; i = e[i].next) {        int to = e[i].to;        if(dep[to] > dep[u] && k != to)            dfs(to,to);    }}LL lx[N],rx[N],mx[N],sum[N],lazy[N],fposs[N];void push_up(int i) {    sum[i] = sum[ls] + sum[rs];    if(rx[ls] == lx[rs]) sum[i]-=1;    lx[i] = lx[ls];rx[i] = rx[rs];}void build(int i,int ll,int rr) {    if(ll == rr) {        lx[i] = fposs[ll];        rx[i] = fposs[ll];        sum[i] = 1;        return ;    }    build(ls,ll,mid),build(rs,mid+1,rr);    push_up(i);}void push_down(int i,int ll,int rr) {    if(lazy[i] && ll != rr) {        lazy[ls] = lazy[i];        lazy[rs] = lazy[i];        lx[ls] = lazy[i];        rx[ls] = lazy[i];        lx[rs] = lazy[i];        rx[rs] = lazy[i];        sum[ls] = 1;        sum[rs] = 1;        lazy[i] = 0;    }}void update(int i,int ll,int rr,int x,int y,int c) {    push_down(i,ll,rr);    if(ll == x && rr == y) {        lazy[i] = c;        lx[i] = c;        rx[i] = c;        sum[i] = 1;        return ;    }    if(y <= mid) update(ls,ll,mid,x,y,c);    else if(x > mid) update(rs,mid+1,rr,x,y,c);    else {        update(ls,ll,mid,x,mid,c);        update(rs,mid+1,rr,mid+1,y,c);    }    push_up(i);}void change(int x,int y,int c) {    while(top[x] != top[y]) {        if(dep[top[x]] < dep[top[y]]) swap(x,y);        update(1,1,n,pos[top[x]],pos[x],c);        x = fa[top[x]];    }    if(dep[x] > dep[y]) swap(x,y);    update(1,1,n,pos[x],pos[y],c);}int query(int i,int ll,int rr,int x,int y) {   push_down(i,ll,rr);    if(ll == x && rr == y) return sum[i];    if(y <= mid) return query(ls,ll,mid,x,y);    else if(x > mid) return query(rs,mid+1,rr,x,y);    else return (query(ls,ll,mid,x,mid) + query(rs,mid+1,rr,mid+1,y) - (lx[rs] == rx[ls]));    push_up(i);}int color(int i,int ll,int rr,int x) {    push_down(i,ll,rr);    if(ll == rr) return lx[i];    if(x <= mid) return color(ls,ll,mid,x);    else return color(rs,mid+1,rr,x);    push_up(i);}int query(int x,int y) {    int res = 0,lastx = -1,lasty = -1;    while(top[x] != top[y]) {        if(dep[top[x]] > dep[top[y]]) {            res += query(1,1,n,pos[top[x]],pos[x]);            if(color(1,1,n,pos[x]) == lastx) res--;            lastx = color(1,1,n,pos[top[x]]);            x = fa[top[x]];        }        else {            res += query(1,1,n,pos[top[y]],pos[y]);            if(color(1,1,n,pos[y]) == lasty) res--;            lasty = color(1,1,n,pos[top[y]]);            y = fa[top[y]];        }    }    if(dep[x] < dep[y])res += query(1,1,n,pos[x],pos[y]);    else res += query(1,1,n,pos[y],pos[x]);    if(color(1,1,n,pos[x]) == lastx) res--;    if(color(1,1,n,pos[y]) == lasty) res--;    return res;}int Q,a[N],x,y;char ch[N];int main() {    scanf("%d%d",&n,&Q);    for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);    for(int i = 1; i < n; ++i) {        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);    }    dfs(1);    dfs(1,1);    for(int i = 1; i <= n; ++i) fposs[pos[i]] = a[i];    build(1,1,n);    while(Q--) {        int a,b,c;        scanf("%s",ch);        if(ch[0] == Q) {            scanf("%d%d",&a,&b);            printf("%d\n",query(a,b));        }else {            scanf("%d%d%d",&a,&b,&c);            change(a,b,c);        }    }    return 0;}/*6 52 2 1 2 1 11 21 32 42 52 6Q 3 5C 2 1 1Q 3 5C 5 1 2Q 3 5*/

 

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并