主要思路:树链剖分 + 线段树
一看就知道是棵树,可以通过树链剖分后维护。
颜色就相当于点权,强烈暗示树链剖分。
所以重点就落在了如何维护区间颜色块数?
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; }