BZOJ2243: [SDOI2011]染色
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9235 Solved: 3469
[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
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
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
Source
【题解】
树剖+sgt,维护色块数,左边颜色,右边颜色,注意颜色可以为0
询问的时候,用t1,t2分别维护左右两条链的sgt节点合并,以及单链情况的时候,看看是u跳还是v跳(比较深度),决定应该与t1合并还是与t2合并
t1 t2方向相反,交换其中一个的lc,rc,合并t1,t2即为询问答案
修改略
还因为build的时候,把tid当rank了。。。全WA。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <map> 9 #include <string> 10 #include <cmath> 11 #define min(a, b) ((a) < (b) ? (a) : (b)) 12 #define max(a, b) ((a) > (b) ? (a) : (b)) 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 14 template<class T> 15 inline void swap(T &a, T &b) 16 { 17 T tmp = a;a = b;b = tmp; 18 } 19 inline void read(int &x) 20 { 21 x = 0;char ch = getchar(), c = ch; 22 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 23 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 24 if(c == '-') x = -x; 25 } 26 const int INF = 0x3f3f3f3f; 27 const int MAXN = 1000000 + 10; 28 int n,m,start[MAXN],rank[MAXN],tim,size[MAXN],top[MAXN],son[MAXN],deep[MAXN],fa[MAXN],tid[MAXN], head[MAXN], cnt; 29 struct Edge 30 { 31 int u,v,nxt; 32 Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;} 33 Edge(){} 34 }edge[MAXN << 1]; 35 inline void insert(int a, int b) 36 { 37 edge[++cnt] = Edge(a,b,head[a]); 38 head[a] = cnt; 39 } 40 struct Node 41 { 42 int l,r,sum,lc,rc,lazy; 43 Node(){l = r = lazy = lc = rc = -1;sum = 0;} 44 }node[MAXN << 2]; 45 Node merge(Node &a, Node &b) 46 { 47 if(a.l == -1) return b; 48 else if(b.l == -1) return a; 49 Node re; 50 re.l = a.l, re.r = b.r, re.sum = a.sum + b.sum; 51 if(a.rc == b.lc && a.rc != -1) -- re.sum; 52 re.lc = a.lc, re.rc = b.rc; 53 return re; 54 } 55 void pushup(int o) 56 { 57 if(node[o].lazy == -1) return; 58 node[o << 1].lazy = node[o << 1 | 1].lazy = node[o].lazy; 59 node[o << 1].sum = node[o << 1 | 1].sum = 1; 60 node[o << 1].lc = node[o << 1].rc = node[o << 1 | 1].lc = node[o << 1 | 1].rc = node[o].lazy; 61 node[o].lazy = -1; 62 } 63 void build(int o = 1, int l = 1, int r = n) 64 { 65 if(l == r) 66 { 67 node[o].l = l,node[o].r = r,node[o].sum = 1,node[o].lc = node[o].rc = start[rank[l]]; 68 return; 69 } 70 int mid = (l + r) >> 1; 71 build(o << 1, l, mid); 72 build(o << 1 | 1, mid + 1, r); 73 node[o] = merge(node[o << 1], node[o << 1 | 1]); 74 } 75 void modify(int ll, int rr, int k, int o = 1) 76 { 77 pushup(o); 78 if(ll <= node[o].l && rr >= node[o].r) 79 { 80 node[o].lc = node[o].rc = node[o].lazy = k; 81 node[o].sum = 1; 82 return; 83 } 84 int mid = (node[o].l + node[o].r) >> 1; 85 if(mid >= ll) modify(ll, rr, k, o << 1); 86 if(mid < rr) modify(ll, rr, k, o << 1 | 1); 87 node[o] = merge(node[o << 1], node[o << 1 | 1]); 88 } 89 Node ask(int ll, int rr, int o = 1) 90 { 91 pushup(o); 92 if(ll <= node[o].l && rr >= node[o].r) return node[o]; 93 Node a, b; 94 int mid = (node[o].l + node[o].r) >> 1; 95 if(mid >= ll) a = ask(ll, rr, o << 1); 96 if(mid < rr) b = ask(ll, rr, o << 1 | 1); 97 return merge(a, b); 98 } 99 void dfs1(int x) 100 { 101 size[x] = 1; 102 for(int pos = head[x];pos;pos = edge[pos].nxt) 103 { 104 int v = edge[pos].v; 105 if(v == fa[x]) continue; 106 deep[v] = deep[x] + 1, fa[v] = x, dfs1(v), size[x] += size[v]; 107 if(son[x] == -1 || size[v] > size[son[x]]) son[x] = v; 108 } 109 } 110 void dfs2(int u, int tp) 111 { 112 top[u] = tp, tid[u] = ++ tim, rank[tim] = u; 113 if(son[u] == -1) return; 114 dfs2(son[u], tp); 115 for(int pos = head[u];pos;pos = edge[pos].nxt) 116 { 117 int v = edge[pos].v; 118 if(v != son[u] & v != fa[u]) dfs2(v, v); 119 } 120 } 121 int query(int u, int v) 122 { 123 int f1 = top[u], f2 = top[v], tag = 1; 124 Node t1, t2, tmp; 125 while(f1 != f2) 126 { 127 if(deep[f1] < deep[f2]) swap(f1, f2), swap(u, v), swap(t1, t2); 128 tmp = ask(tid[f1], tid[u]); 129 t1 = merge(tmp, t1); 130 u = fa[f1];f1 = top[u]; 131 } 132 if(deep[u] > deep[v]) swap(u, v); 133 else if(deep[u] < deep[v]) swap(t1, t2); 134 tmp = ask(tid[u], tid[v]); 135 t1= merge(tmp, t1);swap(t1.lc, t1.rc); 136 tmp = merge(t1, t2); 137 return tmp.sum; 138 } 139 void change(int u, int v, int c) 140 { 141 int f1 = top[u], f2 = top[v]; 142 while(f1 != f2) 143 { 144 if(deep[f1] < deep[f2]) swap(f1, f2), swap(u, v); 145 modify(tid[f1], tid[u], c); 146 u = fa[f1], f1 = top[u]; 147 } 148 if(deep[u] > deep[v]) swap(u, v); 149 modify(tid[u], tid[v], c); 150 } 151 int tmp1,tmp2,tmp3; 152 char c; 153 int main() 154 { 155 read(n), read(m); 156 for(int i = 1;i <= n;++ i) read(start[i]); 157 for(int i = 1;i < n;++ i) read(tmp1), read(tmp2), insert(tmp1, tmp2), insert(tmp2, tmp1); 158 memset(son, -1, sizeof(son)), dfs1(1), dfs2(1,1), build(); 159 for(int i = 1;i <= m;++ i) 160 { 161 scanf("%s", &c); 162 if(c == 'Q') read(tmp1), read(tmp2), printf("%d\n", query(tmp1, tmp2)); 163 else read(tmp1), read(tmp2), read(tmp3), change(tmp1, tmp2, tmp3); 164 } 165 return 0; 166 }