主要思路:树链剖分 + 线段树
一看就知道是棵树,可以通过树链剖分后维护。
颜色就相当于点权,强烈暗示树链剖分。
所以重点就落在了如何维护区间颜色块数?
1 1 2 2 3 3 3 2
我们可以这样考虑:
我们考虑小区间与小区间是不是可以合并。
如:
1 1 2 2 3 3 3 2
假如我们已经知道这左右两段的左右端点和各自的颜色块数,我们可以想象一下对接这两个区间,如果左半段右端点和右半段左端点是一样的话,合起来的区间就会比原来两段区间中颜色块数之和少一个颜色块。
合并的问题解决了,那如何算其中一个区间的颜色块数?
我们和刚刚的方法相似,就是把这个区间分开,然后按照刚刚的办法合并,合并时把同块的减掉,,,
如果一直分下去,,是不是和什么数据结构有点类似,,,
线段树!
我们可以拿线段树模拟出来刚刚的过程,,,
于是这道题就就这么愉快的结束了
我不会告诉你我一个读入写错了交了一页的0分代码
代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 2147483647
#define ll long long
#define ld long double
#define fi first
#define se second
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
//#define LOCAL
#define mod
#define Debug(...) fprintf(stderr, __VA_ARGS__)
inline int read(){
int f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
//This is AC head above...
int n, m;
struct edge{
int v, nxt;
} e[mn << 1];
int p, h[mn];
inline void add(int a,int b){
e[++p].nxt = h[a], h[a] = p, e[p].v = b;
}
int w[mn], dep[mn], sze[mn], fa[mn], son[mn], id[mn], ptn[mn], b[mn], top[mn], cnt;
// Array
struct tree{
int l, r, lc, rc, sum, col;
tree(int _l = 0, int _r = 0, int _lc = 0, int _rc = 0, int _sum = 0, int _col = 0)
: l(_l), r(_r), lc(_lc), rc(_rc), sum(_sum), col(_col) {}
};
struct segmenttree{
tree z[mn << 2];
inline void update(int rt){
z[rt].sum = z[rt << 1].sum + z[rt << 1 | 1].sum;
if(z[rt<<1].rc == z[rt<<1|1].lc)
z[rt].sum--;
z[rt].lc = z[rt << 1].lc;
z[rt].rc = z[rt << 1 | 1].rc;
}
inline void color(int l,int r,int rt,int v){
z[rt].lc = z[rt].rc = v;
z[rt].sum = 1;
z[rt].col = v;
}
inline void push_col(int l,int r,int rt){
if(z[rt].col){
int m = (l + r) >> 1;
color(lson, z[rt].col);
color(rson, z[rt].col);
z[rt].col = 0;
}
}
inline void build(int l,int r,int rt){
if(l==r){
z[rt].lc = z[rt].rc = b[l];
z[rt].sum = 1;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
update(rt);
}
inline void modify(int l,int r,int rt,int nowl,int nowr,int v){
if(nowl<=l && r<=nowr){
color(bson, v);
return;
}
int m = (l + r) >> 1;
push_col(bson);
if(nowl<=m)
modify(lson, nowl, nowr, v);
if(m<nowr)
modify(rson, nowl, nowr, v);
update(rt);
}
inline tree query(int l,int r,int rt,int nowl,int nowr){
if(nowl<=l && r<=nowr){
return z[rt];
}
int m = (l + r) >> 1;
push_col(bson);
if(nowl<=m){
if(m<nowr){
tree res, ltr = query(lson, nowl, nowr), rtr = query(rson, nowl, nowr);
res.sum = ltr.sum + rtr.sum + (ltr.rc == rtr.lc ? -1 : 0);
res.lc = ltr.lc, res.rc = rtr.rc;
return res;
}else{
return query(lson, nowl, nowr);
}
}else{
return query(rson, nowl, nowr);
}
}
} tr;
// line segment tree
void dfs1(int x,int f,int deep){
dep[x] = deep;
fa[x] = f;
sze[x] = 1;
int maxson = -1;
rep(i,x){
int v = e[i].v;
if(v==f)
continue;
dfs1(v, x, deep + 1);
sze[x] += sze[v];
if(maxson<sze[v])
maxson = sze[v], son[x] = v;
}
}
void dfs2(int x,int topf){
id[x] = ++cnt;
ptn[id[x]] = x;
b[id[x]] = w[x];
top[x] = topf;
if(!son[x])
return;
dfs2(son[x], topf);
rep(i,x){
int v = e[i].v;
if(v==fa[x]||v==son[x])
continue;
dfs2(v, v);
}
}
// DFS
inline void tree_modify(int x,int y,int v){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
swap(x, y);
tr.modify(root, id[top[x]], id[x], v);
x = fa[top[x]];
}
if(dep[x] > dep[y])
swap(x, y);
tr.modify(root, id[x], id[y], v);
}
inline int tree_query(int x,int y){
int sum = 0, lxx = 0, sxy = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
swap(x, y), swap(lxx, sxy);
tree res = tr.query(root, id[top[x]], id[x]);
sum += res.sum;
if(res.rc == lxx)
sum--;
lxx = res.lc;
x = fa[top[x]];
}
if(dep[x] > dep[y])
swap(x, y), swap(lxx, sxy);
tree res = tr.query(root, id[x], id[y]);
sum += res.sum;
if(res.lc == lxx)
sum--;
if(res.rc == sxy)
sum--;
return sum;
}
int main(){
n = read(), m = read();
go(i, 1, n, 1) w[i] = read();
go(i, 1, n - 1, 1){
int a = read(), b = read();
add(a, b), add(b, a);
}
dfs1(1, 1, 1);
dfs2(1, 1);
tr.build(root);
go(i, 1, m, 1){
char c;
cin >> c;
int x = read(), y = read();
if(c=='Q')
cout << tree_query(x, y) << "\n";
else{
int v = read();
tree_modify(x, y, v);
}
}
#ifdef LOCAL
Debug("\nMy Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}