[原创]BZOJ 2243: [SDOI2011]染色 [树链剖分+细节]【数据结构】

2017-04-18 20:20:01 Tabris_ 阅读数:585


博客爬取于2020-06-14 22:40:59
以下为正文

版权声明:本文为Tabris原创文章,未经博主允许不得私自转载。
https://blog.csdn.net/qq_33184171/article/details/70232210


题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243
————————————————————————————————————————————————
2243: [SDOI2011]染色

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 7492 Solved: 2803
[Submit][Status][Discuss]
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,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“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]之间。

Source

第一轮day1

————————————————————————————————————————————————

在树上两点间的路上进行修改 那么就是树链剖分,
根据操作 是区间染色 所以要用线段树维护

注意在维护的时候线段树上的每个点要多维护一个最左边和最右边的颜色。
方便合并的时候计算颜色个数

然后就是注意颜色可能为0
lazy标记的时候改成-1, 习惯性的用0 WA到死啊。

附本题代码

————————————————————————————————————————

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# include <bits/stdc++.h>
using namespace std;

const int N = 1e5+7;

/***************************************/

int n,m;
int c[N];
vector<int >G[N];

int fa[N],sz[N],son[N],dep[N];

int dfs1(int u,int f,int d){
fa[u]=f,sz[u]=1,son[u]=0,dep[u]=d;
int gz = G[u].size();
for(int to,i=0;i<gz;i++){
to = G[u][i];
if(to==f) continue;
dfs1(to,u,d+1);
sz[u]+=sz[to];
if(sz[son[u]]<sz[to]) son[u]=to;
}
}

int top[N],tree[N],pre[N],cnt;

int dfs2(int u,int tp){
top[u]=tp,tree[u]=++cnt,pre[tree[u]]=u;
if(son[u]) dfs2(son[u],tp);
int gz = G[u].size();
for(int to,i=0;i<gz;i++){
to = G[u][i];
if(to==fa[u]||to==son[u])continue;
dfs2(to,to);
}
}

int sum[N<<2],lazy[N<<2],lc[N<<2],rc[N<<2];

void pushup(int rt){
sum[rt] = sum[rt<<1]+sum[rt<<1|1]-(rc[rt<<1] == lc[rt<<1|1]);
lc[rt]=lc[rt<<1],rc[rt]=rc[rt<<1|1];
}

void pushdown(int rt){
if(lazy[rt]!=-1){
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum [rt<<1] = sum [rt<<1|1] = 1;
lc[rt<<1] = rc[rt<<1] = lazy[rt];
lc[rt<<1|1] = rc[rt<<1|1] = lazy[rt];
lazy[rt]=-1;
}
}

void build(int rt,int l,int r){
if(l==r){
sum[rt]=1,rc[rt]=lc[rt]=c[pre[l]];
return ;
}
int m = (r+l)>>1;
build(rt<<1 ,l ,m);
build(rt<<1|1,m+1,r);
pushup(rt);
}

void update(int rt,int l,int r,int L,int R,int clr){
if(L<=l&&r<=R){
rc[rt]=lc[rt]=lazy[rt]=clr;
sum[rt] = 1;
return ;
}
pushdown(rt);
int m = (r+l)>>1;
if(L<=m) update(rt<<1 ,l ,m,L,R,clr);
if(R> m) update(rt<<1|1,m+1,r,L,R,clr);
pushup(rt);
return ;
}

int query(int rt,int l,int r,int L,int R){
if(L>R) return 0;
if(L<=l&&r<=R) return sum[rt];
pushdown(rt);
int ans = 0,m = (r+l)>>1;
if(R<=m) ans = query(rt<<1 ,l, m,L,R);
else if(L>m) ans = query(rt<<1|1,m+1,r,L,R);
else ans = query(rt<<1 ,l, m,L,R)+
query(rt<<1|1,m+1,r,L,R)-
(rc[rt<<1]==lc[rt<<1|1]);
pushup(rt);
return ans;
}

int query_color(int rt,int l,int r,int pos){
if(l==r) return lc[rt];
pushdown(rt);
int m = (r+l)>>1,ans;
if(pos<=m) ans = query_color(rt<<1 ,l ,m,pos);
else ans = query_color(rt<<1|1,m+1,r,pos);
pushup(rt);
return ans;
}

void init(){
cnt = 0;
for(int i=1;i<=n;i++)G[i].clear();
memset(sum,0,sizeof(sum));
memset(lazy,-1,sizeof(lazy));
};

void brush(int x,int y,int clr){
int fx = top[x],fy = top[y];
while(fx!=fy){
if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
update(1,1,n,tree[fx],tree[x],clr);
x = fa[fx],fx = top[x];
}
if(tree[x]>tree[y]) swap(x,y);
update(1,1,n,tree[x],tree[y],clr);
return ;
}

void solve(int x,int y){
int fx = top[x],fy = top[y];
int ans = 0;
while(fx!=fy){
if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
ans += query(1,1,n,tree[fx],tree[x]);
if(query_color(1,1,n,tree[fa[fx]]) == query_color(1,1,n,tree[fx])) ans--;
x = fa[fx],fx = top[x];
}
if(tree[x]>tree[y]) swap(x,y);
ans += query(1,1,n,tree[x],tree[y]);
printf("%d\n",ans);
return ;
}

int main(){
while(~scanf("%d%d",&n,&m)){
init();

for(int i=1;i<=n;i++) scanf("%d",&c[i]);

for(int i=2,u,v;i<=n;i++){
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}

dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);

int l,r,x;
char a[10];
while(m--){
scanf("%s",a);
scanf("%d %d",&l,&r);
if(a[0]=='C'){
scanf("%d",&x);
brush(l,r,x);
}
else solve(l,r);
}
}
return 0;
}