bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 4637  Solved: 1726
[Submit][Status][Discuss]

Description

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

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

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

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

Input

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

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

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

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

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

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

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]之间。

Source

【思路】

       树链剖分,线段树

       线段树维护lc rc c s分别表示线段的左右端颜色 update设置颜色 线段所含颜色数,需要注意的是线段合并以及统计信息时候需要考虑两线段接点是否重色。

       Ps:dep比较的是top,T-T    节点信息加上lr倒是个不错的写法 :)

【代码】

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<iostream>
  5 #include<algorithm>
  6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
  7 using namespace std;
  8 
  9 const int N = 1e5+1e5+10;
 10 
 11 struct Node {
 12     int l,r,lc,rc,c,s;
 13 }T[N<<1];
 14 vector<int> G[N];
 15 int n,m,z,c[N];
 16 char s[2];
 17 
 18 int w[N],top[N],son[N],siz[N],fa[N],dep[N];
 19 
 20 void dfs1(int u) {
 21     siz[u]=1; son[u]=0;
 22     for(int i=0;i<G[u].size();i++) {
 23         int v=G[u][i];
 24         if(v!=fa[u]) {
 25             fa[v]=u; dep[v]=dep[u]+1;
 26             dfs1(v);
 27             if(siz[v]>siz[son[u]]) son[u]=v;
 28             siz[u]+=siz[v];
 29         }
 30     }
 31 }
 32 void dfs2(int u,int tp) {
 33     w[u]=++z; top[u]=tp;
 34     if(son[u]) dfs2(son[u],tp);
 35     for(int i=0;i<G[u].size();i++) {
 36         int v=G[u][i];
 37         if(v!=son[u] && v!=fa[u]) dfs2(v,v);
 38     }
 39 }
 40 void pushdown(int u) {
 41     if(T[u].c!=-1 && T[u].l<T[u].r) {
 42         int lc=u<<1 , rc=lc|1;
 43         T[lc].c=T[rc].c=T[u].c;
 44         T[lc].lc=T[lc].rc=T[rc].lc=T[rc].rc=T[u].c;
 45         T[lc].s=T[rc].s=1;
 46         T[u].c=-1;
 47     }
 48 }
 49 void maintain(int u) {
 50     int lc=u<<1,rc=lc|1;
 51     T[u].lc=T[lc].lc , T[u].rc=T[rc].rc;
 52     T[u].s=T[lc].s+T[rc].s-(T[lc].rc==T[rc].lc);
 53 }
 54 void build(int u,int L,int R) {
 55     T[u].l=L , T[u].r=R , T[u].c=-1 , T[u].s=1;
 56     if(L==R) return ;
 57     int M=(L+R)>>1;
 58     build(u<<1,L,M) , build(u<<1|1,M+1,R);
 59 }
 60 void update(int u,int L,int R,int x) {
 61     pushdown(u);
 62     if(L==T[u].l && R==T[u].r) {                //CC
 63         T[u].c=T[u].lc=T[u].rc=x;
 64         T[u].s=1; return ;
 65     }
 66     int M=(T[u].l+T[u].r)>>1 , lc=u<<1 , rc=lc|1;
 67     if(R<=M) update(lc,L,R,x);                    //can change
 68     else if(L>M) update(rc,L,R,x);
 69     else
 70         update(lc,L,M,x) , update(rc,M+1,R,x);
 71     maintain(u);
 72 }
 73 int query(int u,int L,int R) {
 74     pushdown(u);
 75     if(L==T[u].l && R==T[u].r) return T[u].s;
 76     int M=(T[u].l+T[u].r)>>1 , lc=u<<1 , rc=lc|1;
 77     if(R<=M) return query(lc,L,R);
 78     else if(L>M) return query(rc,L,R);
 79     else
 80         return query(lc,L,M)+query(rc,M+1,R)-(T[lc].rc==T[rc].lc);
 81 }
 82 int find(int u,int r) {
 83     pushdown(u);
 84     if(T[u].l==T[u].r) return T[u].lc;
 85     int M=(T[u].l+T[u].r)>>1;
 86     return r<=M? find(u<<1,r):find(u<<1|1,r);
 87 }
 88 void modify(int u,int v,int x) {
 89     while(top[u]!=top[v]) {
 90         if(dep[top[u]]<dep[top[v]]) swap(u,v);
 91         update(1,w[top[u]],w[u],x);
 92         u=fa[top[u]];
 93     }
 94     if(dep[u]>dep[v]) swap(u,v);
 95     update(1,w[u],w[v],x);
 96 }
 97 int ask(int u,int v) {
 98     int ans=0;
 99     while(top[u]!=top[v]) {
100         if(dep[top[u]]<dep[top[v]]) swap(u,v);
101         ans+=query(1,w[top[u]],w[u]);
102         if(find(1,w[fa[top[u]]])==find(1,w[top[u]])) ans--;
103         u=fa[top[u]];
104     }
105     if(dep[u]>dep[v]) swap(u,v);
106     ans+=query(1,w[u],w[v]);
107     return ans;
108 }
109 
110 void read(int& x) {
111     char c=getchar();
112     while(!isdigit(c)) c=getchar();
113     x=0;
114     while(isdigit(c)) 
115         x=x*10+c-'0' , c=getchar();
116 }
117 int main() {
118     read(n) , read(m);
119     FOR(i,1,n) read(c[i]);
120     int u,v,k;
121     FOR(i,1,n-1) {
122         read(u) , read(v);
123         G[u].push_back(v);
124         G[v].push_back(u);
125     }
126     dfs1(1) , dfs2(1,1);
127     build(1,1,n);
128     FOR(i,1,n) update(1,w[i],w[i],c[i]);
129     while(m--) {
130         scanf("%s",s);
131         read(u) , read(v);
132         if(s[0]=='C')
133             read(k) , modify(u,v,k);
134         else
135             printf("%d
",ask(u,v));
136     }
137     return 0;
138 }
原文地址:https://www.cnblogs.com/lidaxin/p/5185642.html