[SDOI2011]染色
一看就知道是一道树剖题。
先树剖转换成线性,然后线段树维护。
维护的时候跟酒店那道题有点像,但比那个简单多了。
首先一个sum代表颜色段数量,然后除了lazy之外还有lco,rco分别代表区间左右端点是啥颜色。
合并的时候除了sum[now] = sum[now <<1] + sum[now << 1 |1]外,还要考虑左右子区间靠在一起的地方颜色是否相等,即rco[now << 1] == lco[now << 1 | 1],是的话就要减一。
查询的时候需要注意链的顶端的父亲结点和链的顶端结点颜色是否相同,是的话答案还是要--。这个单独写一个线段树单点查询的函数就行,很短。
p.s.emacs的格式就是丑,凑合着看吧
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e5 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), las = ' '; 25 while(!isdigit(ch)) las = ch, ch = getchar(); 26 while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar(); 27 if(las == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) putchar('-'), x = -x; 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, m, a[maxn]; 38 vector<int> v[maxn]; 39 40 bool vis[maxn]; 41 int dep[maxn], fa[maxn], siz[maxn], son[maxn]; 42 void dfs1(int now) 43 { 44 vis[now] = 1; siz[now] = 1; 45 for(int i = 0; i < (int)v[now].size(); ++i) 46 { 47 if(!vis[v[now][i]]) 48 { 49 dep[v[now][i]] = dep[now] + 1; 50 fa[v[now][i]] = now; 51 dfs1(v[now][i]); 52 siz[now] += siz[v[now][i]]; 53 if(!son[now] || siz[son[now]] < siz[v[now][i]]) son[now] = v[now][i]; 54 } 55 } 56 } 57 int dfsx[maxn], pos[maxn], top[maxn], cnt = 0; 58 void dfs2(int now) 59 { 60 dfsx[now] = ++cnt; pos[cnt] = now; 61 vis[now] = 1; 62 if(son[now]) 63 { 64 top[son[now]] = top[now]; 65 dfs2(son[now]); 66 } 67 for(int i = 0; i < (int)v[now].size(); ++i) 68 { 69 if(!vis[v[now][i]] && v[now][i] != son[now]) 70 { 71 top[v[now][i]] = v[now][i]; 72 dfs2(v[now][i]); 73 } 74 } 75 } 76 77 struct Tree 78 { 79 int l, r; 80 int sum, lco, rco, lzy; 81 Tree operator + (const Tree& other)const 82 { 83 Tree ret; 84 ret.l = l; ret.r = other.r; 85 ret.lzy = -1; 86 ret.sum = sum + other.sum; 87 if(rco == other.lco) ret.sum--; 88 ret.lco = lco; ret.rco = other.rco; 89 return ret; 90 } 91 }t[maxn << 2]; 92 93 void build(int L, int R, int now) 94 { 95 t[now].l = L; t[now].r = R; 96 t[now].lzy = -1; 97 if(L == R) 98 { 99 t[now].sum = 1; 100 t[now].lco = t[now].rco = a[pos[L]]; 101 return; 102 } 103 int mid = (L + R) >> 1; 104 build(L, mid, now << 1); 105 build(mid + 1, R, now << 1 | 1); 106 t[now] = t[now << 1] + t[now << 1 | 1]; 107 } 108 void pushdown(int now) 109 { 110 if(t[now].lzy != -1) 111 { 112 t[now << 1].sum = t[now << 1 | 1].sum = 1; 113 t[now << 1].lzy = t[now << 1 | 1].lzy = t[now].lzy; 114 t[now << 1].lco = t[now << 1].rco = t[now].lzy; 115 t[now << 1 | 1].lco = t[now << 1 | 1].rco = t[now].lzy; 116 t[now].lzy = -1; 117 } 118 } 119 void update(int L, int R, int now, int d) 120 { 121 if(L == t[now].l && R == t[now].r) 122 { 123 t[now].sum = 1; 124 t[now].lco = t[now].rco = d; 125 t[now].lzy = d; return; 126 } 127 pushdown(now); 128 int mid = (t[now].l + t[now].r) >> 1; 129 if(R <= mid) update(L, R, now << 1, d); 130 else if(L > mid) update(L, R, now << 1 | 1, d); 131 else update(L, mid, now << 1, d), update(mid + 1, R, now << 1 | 1, d); 132 t[now] = t[now << 1] + t[now << 1 | 1]; 133 } 134 int query(int L, int R, int now) 135 { 136 if(L == t[now].l && R == t[now].r) return t[now].sum; 137 pushdown(now); 138 int mid = (t[now].l + t[now].r) >> 1; 139 if(R <= mid) return query(L, R, now << 1); 140 else if(L > mid) return query(L, R, now << 1 | 1); 141 else 142 { 143 int ret = query(L, mid, now << 1) + query(mid + 1, R, now << 1 | 1); 144 if(t[now << 1].rco == t[now << 1 | 1].lco) ret--; 145 return ret; 146 } 147 } 148 int query_col(int x, int now) 149 { 150 if(t[now].l == t[now].r) return t[now].lco; 151 pushdown(now); 152 int mid = (t[now].l + t[now].r) >> 1; 153 if(x <= mid) return query_col(x, now << 1); 154 else return query_col(x, now << 1 | 1); 155 } 156 157 void update_path(int x, int y, int d) 158 { 159 while(top[x] != top[y]) 160 { 161 if(dep[top[x]] < dep[top[y]]) swap(x, y); 162 update(dfsx[top[x]], dfsx[x], 1, d); 163 x = fa[top[x]]; 164 } 165 if(dep[x] > dep[y]) swap(x, y); 166 update(dfsx[x], dfsx[y], 1, d); 167 } 168 int query_path(int x, int y) 169 { 170 int ret = 0; 171 while(top[x] != top[y]) 172 { 173 if(dep[top[x]] < dep[top[y]]) swap(x, y); 174 ret += query(dfsx[top[x]], dfsx[x], 1); 175 if(query_col(dfsx[top[x]], 1) == query_col(dfsx[fa[top[x]]], 1)) ret--; 176 x = fa[top[x]]; 177 } 178 if(dep[x] > dep[y]) swap(x, y); 179 ret += query(dfsx[x], dfsx[y], 1); 180 return ret; 181 } 182 183 char c[2]; 184 185 int main() 186 { 187 n = read(); m = read(); 188 for(int i = 1; i <= n; ++i) a[i] = read(); 189 for(int i = 1; i < n; ++i) 190 { 191 int x = read(), y = read(); 192 v[x].push_back(y); v[y].push_back(x); 193 } 194 dfs1(1); Mem(vis, 0); 195 top[1] = 1; dfs2(1); 196 build(1, cnt, 1); 197 for(int i = 1; i <= m; ++i) 198 { 199 scanf("%s", c); int L = read(), R = read(); 200 if(c[0] == 'C') 201 { 202 int x = read(); 203 update_path(L, R, x); 204 } 205 else write(query_path(L, R)), enter; 206 } 207 return 0; 208 }