HYSBZ 2243 染色

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

题意:

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

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

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

思路:

权值在点上的树链剖分+线段树成段更新+线段树成段询问。

维护颜色端的数量方法:

如果左儿子区间的最右端颜色与右儿子区间的最左端区间相同。

sum[rt] = sum[rt<<1]+sum[rt<<1|1] - 1;

否则sum[rt] = sum[rt<<1]+sum[rt<<1|1];

树链剖分部分也进行相应维护。

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdio>
  5 #include <vector>
  6 using namespace std;
  7 int n, q;
  8 #define maxn 100010
  9 #define lson l, m, rt<<1
 10 #define rson m+1, r, rt<<1|1
 11 int siz[maxn], top[maxn], fa[maxn], son[maxn], dep[maxn];
 12 int w[maxn], fw[maxn];
 13 int A[maxn];
 14 vector <int> mp[maxn];
 15 int pos;
 16 int Left, Right;
 17 int sum[maxn<<2], cl[maxn<<2], cr[maxn<<2], col[maxn<<2];
 18 void PushUp(int rt)
 19 {
 20     if(cr[rt<<1] == cl[rt<<1|1]) sum[rt] = sum[rt<<1] + sum[rt<<1|1] - 1;
 21     else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 22     cl[rt] = cl[rt<<1];
 23     cr[rt] = cr[rt<<1|1];
 24 }
 25 void PushDown(int rt, int m)
 26 {
 27     if(col[rt] >= 0)
 28     {
 29         col[rt<<1] = col[rt<<1|1] = col[rt];
 30         sum[rt<<1] = sum[rt<<1|1] = 1;
 31         cl[rt<<1] = cl[rt<<1|1] = cr[rt<<1] = cr[rt<<1|1] = cl[rt];
 32         col[rt] = -1;
 33     }
 34 }
 35 void build(int l, int r, int rt)
 36 {
 37     col[rt] = -1;
 38     if(l == r)
 39     {
 40         cl[rt] = cr[rt] = A[fw[l]];
 41         sum[rt] = 1;
 42         return;
 43     }
 44     int m = (l+r)>>1;
 45     build(lson);
 46     build(rson);
 47     PushUp(rt);
 48 }
 49 void update(int L, int R, int c, int l, int r, int rt)
 50 {
 51     if(L <= l && R >= r)
 52     {
 53         col[rt] = c; sum[rt] = 1; cl[rt] = c; cr[rt] = c;
 54         return;
 55     }
 56     PushDown(rt, r-l+1);
 57     int m = (l+r)>>1;
 58     if(L <= m) update(L, R, c, lson);
 59     if(R > m) update(L, R, c, rson);
 60     PushUp(rt);
 61 }
 62 int query(int L, int R, int l, int r, int rt)
 63 {
 64     if(l == L) Left = cl[rt];
 65     if(r == R) Right = cr[rt];
 66     if(L <= l && R >= r)
 67     {
 68         return sum[rt];
 69     }
 70     PushDown(rt, r-l+1);
 71     int m = (l+r)>>1;
 72     int ret = 0;
 73     //合并线段树 这里也要修改!
 74     if(R <= m) return query(L, R, lson);
 75     else if(L > m) return query(L, R, rson);
 76     else
 77     {
 78         ret = query(L,R,lson) + query(L, R, rson);
 79         if(cl[rt<<1|1] == cr[rt<<1]) ret --;
 80         return ret;
 81     }
 82     //if(L <= m) ret += query(L, R, lson);
 83     //if(R > m) ret += query(L, R, rson);
 84 }
 85 int dfs1(int u, int pre, int deep)
 86 {
 87     siz[u] = 1; dep[u] = deep; fa[u] = pre;
 88     int mmax = 0;
 89     for(int i = 0; i < mp[u].size(); i++)
 90     {
 91         if(mp[u][i] != pre)
 92         {
 93             int temp = dfs1(mp[u][i], u, deep+1);
 94             siz[u] += temp;
 95             if(son[u] == -1 || temp >= mmax) 
 96             {
 97                 son[u] = mp[u][i];
 98                 mmax = temp;
 99             }
100         }
101     }
102     return siz[u];
103 }
104 void dfs2(int u, int val)
105 {
106     top[u] = val;
107     if(son[u] != -1)
108     {
109         w[u] = ++pos;
110         fw[w[u]] = u;
111         dfs2(son[u], val);
112     }
113     else if(son[u] == -1)
114     {
115         w[u] = ++pos;
116         fw[w[u]] = u;
117         return;
118     }
119     for(int i = 0; i < mp[u].size(); i++)
120     {        
121         if(mp[u][i] != son[u] && mp[u][i] != fa[u]) dfs2(mp[u][i], mp[u][i]);
122     }
123 }
124 int find(int u, int v)
125 {
126     int mark1 = -1, mark2 = -1;
127     int f1 = top[u], f2 = top[v];
128     int temp = 0; int precolor = -1;
129     while(f1 != f2)
130     {
131         if(dep[f1] < dep[f2])   //规定f1更深
132         {
133             swap(f1, f2);
134             swap(u, v);
135             swap(mark1, mark2);  //交替
136         }
137         temp += query(w[f1], w[u], 1, pos, 1);
138         if(Right == mark1) temp --;
139         mark1 = Left;
140         u = fa[f1]; f1 = top[u];
141     }
142     if(dep[u] < dep[v])  //规定u更深
143     {
144         swap(u, v);
145         swap(mark1, mark2);
146     }
147     temp += query(w[v], w[u], 1, pos, 1);
148     if(Right == mark1) temp--;
149     if(Left == mark2) temp--;
150     return temp;
151 }
152 void UPDATE(int u, int v, int color)
153 {
154     int f1 = top[u], f2 = top[v];
155     while(f1 != f2)
156     {
157         if(dep[f1] < dep[f2])
158         {
159             swap(f1, f2);
160             swap(u, v);
161         }
162         update(w[f1], w[u], color, 1, pos, 1);
163         u = fa[f1]; f1 = top[u];
164     }
165     if(dep[u] > dep[v]) swap(u, v);
166     update(w[u], w[v], color, 1, pos, 1);
167 }
168 int main() 
169 {
170     //freopen("in.txt", "r", stdin);
171     while(~scanf("%d%d", &n, &q))
172     {
173         for(int i = 1; i <= n; i++) mp[i].clear(); 
174         pos = 0;
175         memset(son, -1, sizeof(son));
176         for(int i = 1; i <= n; i++) scanf("%d", &A[i]);
177         for(int i = 1; i <= n-1; i++)
178         {
179             int a, b; scanf("%d%d", &a, &b);
180             mp[a].push_back(b);
181             mp[b].push_back(a);
182         }
183         dfs1(1, -1, 1);
184         dfs2(1, 1);
185         build(1, pos, 1);
186         
187         char op[5];
188         while(q--)
189         {
190             scanf("%s", op);
191             int a, b, c;
192             if(op[0] == 'Q')
193             {
194                 scanf("%d%d", &a, &b);
195                 printf("%d\n", find(a, b));
196             }
197             else if(op[0] == 'C')
198             {
199                 scanf("%d%d%d", &a, &b, &c);
200                 UPDATE(a, b, c);
201             }
202         }
203     }
204     return 0;
205 }

 

 

 

posted @ 2015-10-22 18:53  下周LGD该赢了吧  阅读(323)  评论(0编辑  收藏  举报