[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 }
View Code

 

posted @ 2018-09-26 22:34  mrclr  阅读(190)  评论(0编辑  收藏  举报