题目链接:https://www.luogu.org/problem/P2486
思路:
首先我们看到颜色的个数,然后又是一个树上的操作很自然而然的就会想到树链剖分
但是会遇到一个问题,那就是题目并不是直接给你染色颜色的个数的,所以我们先要预处理得到颜色个数
首先我们分情况进行讨论:
第一种情况: 左区间是 1234 (颜色个数4) 右区间是 222 (颜色个数1)
合并后: 1234222 (颜色个数5 = 4 + 1)
没有出现重复
第二种情况: 左区间是 1231 (颜色个数3) 右区间是 121 (颜色个数2)
合并后 1231121 (颜色个数4 = 3 + 2 -1)
左区间的第一个元素和右区间的第一个元素一样,这就会出现重复
我们用 lc[] 和 rc[] 分别代表左区间的颜色 和 右区间的颜色
也就是当 左区间的最后一个元素和右区间的第一个元素一样,那么就重复了
push_up 的操作
叶子结点的左区间的颜色和右区间的颜色是一样的 ,从叶子结点开始往上回溯
tree[nod].lc = tree[nod<<1].lc
tree[nod].rc = tree[(nod<<1)+1].rc
对于颜色个数的操作就是普通的线段树的操作
至于剖分查询的话:
这张图已经非常的清楚了
1 #include <stdio.h> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <math.h> 9 #include <map> 10 11 #define LL long long 12 #define INF 0x3f3f3f3f 13 using namespace std; 14 const int maxn = 2e5 + 10; 15 16 struct Edge{ 17 int to,next; 18 }edge[maxn*2]; 19 20 int tot,head[maxn]; 21 22 void add_edge(int u,int v){ 23 edge[++tot] = Edge{v,head[u]}; 24 head[u] = tot; 25 } 26 27 int fa[maxn]; 28 int dep[maxn]; 29 int siz[maxn]; 30 int son[maxn]; 31 32 void dfs1(int u,int f){ 33 fa[u] = f; 34 dep[u] = dep[f] + 1; 35 siz[u] = 1; 36 int maxsize = -1; 37 for (int i=head[u];~i;i=edge[i].next){ 38 int v = edge[i].to; 39 if (v == f) 40 continue; 41 dfs1(v,u); 42 siz[u] += siz[v]; 43 if (siz[v] > maxsize){ 44 son[u] = v; 45 maxsize = siz[v]; 46 } 47 } 48 } 49 50 int tim; 51 int dfn[maxn]; 52 int w[maxn]; 53 int v[maxn]; 54 int top[maxn]; 55 56 void dfs2(int u,int t){ 57 dfn[u] = ++tim; 58 top[u] = t; 59 w[tim] = v[u]; 60 if (!son[u]) 61 return ; 62 dfs2(son[u],t); 63 for (int i=head[u];~i;i=edge[i].next){ 64 int v = edge[i].to; 65 if (v == fa[u] || v == son[u]) 66 continue; 67 dfs2(v,v); 68 } 69 } 70 71 struct segment_tree{ 72 int l,r; 73 int sum,c; 74 int lazy; 75 int lc,rc; 76 }tree[maxn*4]; 77 78 void pushdown(int nod){ 79 if (tree[nod].lazy != 0 ){ 80 tree[nod<<1].lazy = tree[(nod<<1)+1].lazy = tree[nod].lazy; 81 tree[nod<<1].c = tree[(nod<<1)+1].c = tree[nod].lazy; 82 tree[nod<<1].lc = tree[nod<<1].rc = tree[(nod<<1)+1].lc = tree[(nod<<1)+1].rc = tree[nod].lazy; 83 tree[nod<<1].sum = tree[(nod<<1)+1].sum = 1; 84 tree[nod].lazy = 0; 85 } 86 } 87 88 void build(int l,int r,int nod){ 89 tree[nod].l = l; 90 tree[nod].r = r; 91 if (l == r){ 92 tree[nod].c = w[l]; 93 tree[nod].lc = tree[nod].rc = w[l]; 94 tree[nod].sum = 1; 95 return ; 96 } 97 int mid = (l + r) >> 1; 98 build(l,mid,nod<<1); 99 build(mid+1,r,(nod<<1)+1); 100 tree[nod].sum = (tree[nod<<1].sum + tree[(nod<<1)+1].sum); 101 if (tree[nod<<1].rc == tree[(nod<<1)+1].lc ){ 102 tree[nod].sum -= 1; 103 } 104 tree[nod].lc = tree[nod<<1].lc; 105 tree[nod].rc = tree[(nod<<1)+1].rc; 106 } 107 108 void update(int x,int y,int c,int nod=1){ 109 int l = tree[nod].l,r = tree[nod].r; 110 if (x <= l && y >= r){ 111 tree[nod].c = c; 112 tree[nod].lazy = c; 113 tree[nod].sum = 1; 114 tree[nod].lc = tree[nod].rc = c; 115 return ; 116 } 117 pushdown(nod); 118 int mid = (l + r) >> 1; 119 if (x <= mid){ 120 update(x,y,c,nod<<1); 121 } 122 if (y > mid){ 123 update(x,y,c,(nod<<1)+1); 124 } 125 tree[nod].sum = (tree[nod<<1].sum + tree[(nod<<1)+1].sum); 126 if (tree[nod<<1].rc == tree[(nod<<1)+1].lc ){ 127 tree[nod].sum -= 1; 128 } 129 tree[nod].lc = tree[nod<<1].lc; 130 tree[nod].rc = tree[(nod<<1)+1].rc; 131 } 132 133 int query(int x,int y,int nod=1){ 134 int l = tree[nod].l,r = tree[nod].r; 135 if (x <= l && y >= r){ 136 return tree[nod].sum; 137 } 138 pushdown(nod); 139 int ret = 0; 140 int mid = (l + r) >> 1; 141 if (x <= mid){ 142 ret += query(x,y,nod<<1); 143 } 144 if (y > mid){ 145 ret += query(x,y,(nod<<1)+1); 146 if (x <= mid && tree[nod<<1].rc == tree[(nod<<1)+1].lc ){ 147 ret -= 1; 148 } 149 } 150 return ret; 151 } 152 153 int Qc(int x,int y,int nod=1){ 154 int l = tree[nod].l,r = tree[nod].r; 155 if (x <= l && y >= r){ 156 return tree[nod].c; 157 } 158 pushdown(nod); 159 int mid = (l + r) >> 1; 160 if (x <= mid){ 161 return Qc(x,y,nod<<1); 162 } 163 if (y > mid) 164 return Qc(x,y,(nod<<1)+1); 165 } 166 167 void uprange(int x,int y,int c){ 168 while (top[x] != top[y]){ 169 if (dep[top[x]] < dep[top[y]]) 170 swap(x,y); 171 update(dfn[top[x]],dfn[x],c); 172 x = fa[top[x]]; 173 } 174 if (dep[x] > dep[y]) 175 swap(x,y); 176 update(dfn[x],dfn[y],c); 177 } 178 179 int Qsum(int x,int y){ 180 int ans = 0,Cson,Cfa; 181 while (top[x] != top[y]){ 182 if (dep[top[x]] < dep[top[y]]) 183 swap(x,y); 184 ans += query(dfn[top[x]],dfn[x]); 185 Cfa = Qc(dfn[fa[top[x]]],dfn[fa[top[x]]]); 186 Cson = Qc(dfn[top[x]],dfn[top[x]]); 187 if (Cson == Cfa) 188 ans -= 1; 189 x = fa[top[x]]; 190 } 191 if (dep[x] > dep[y]) 192 swap(x,y); 193 ans += query(dfn[x],dfn[y]); 194 return ans; 195 } 196 197 198 199 int main(){ 200 int n,m; 201 scanf("%d%d",&n,&m); 202 memset(head,-1, sizeof(head)); 203 for (int i=1;i<=n;i++){ 204 scanf("%d",&v[i]); 205 } 206 for (int i=1;i<=n-1;i++){ 207 int x,y; 208 scanf("%d%d",&x,&y); 209 add_edge(x,y); 210 add_edge(y,x); 211 } 212 dfs1(1,0); 213 dfs2(1,1); 214 build(1,n,1); 215 while (m--){ 216 char op[4]; 217 scanf("%s",op); 218 if (op[0] == 'Q'){ 219 int x,y; 220 scanf("%d%d",&x,&y); 221 printf("%d ",Qsum(x,y)); 222 } 223 else { 224 int x,y,z; 225 scanf("%d%d%d",&x,&y,&z); 226 uprange(x,y,z); 227 } 228 } 229 return 0; 230 }
附上dalao的博客:https://www.cnblogs.com/Tony-Double-Sky/p/9283262.html