首先這是個挺裸的題,由於太久沒寫剖分導致調了好久,前天調了一下午,一直查不到錯
昨晚在看春晚的時候突然靈機一動,發現合併的時候出了問題,開電腦把它a掉了= =
感覺自己也蠻拼的給定
一棵有n
個節點的
無根樹和
m個操作
,操作有
2類: 1:
將節點a
到節點b
路徑上所
有點都染
成顏色c
2:詢問節點a
到節點b
路徑上的
顏色段數
量(連續
相同顏色
被認為是
同一段)
,如"112221"由
3段組成
:"11"、
"222"和
"1" 很顯然這是要剖分的辣,然後用線段樹維護資訊。然後我們會發現合併的時候有點蛋疼
它要求顏色段數量,所以我們很自然的想到要維護左右端的顏色資訊來進行合併
線段樹合併時su
m[rt
]=su
m[ls
]+su
m[rs
]−(r
c[ls
]==lc
[rs]
) 即可
但是我們正常在查詢的時候是要在剖分後的樹上」跳來跳去的」
所以每次查詢的時候我們都需要維護當前左右端顏色資訊,然後在」跳」的過程中合併
注意顏色是[0
,109]
的,所以
打標記時
要開始賦
值為−1
合併的時候想清楚,注意細節就好辣!可以仔細想想或者詳情參見**qvq
#include //樹鏈剖分
using namespace std;
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const int n = 100005, m = n << 2;
int n, m, lcol, rcol, tot, cnt, w[n], q[n], top[n], sz[n], son[n], pre[n], id[n], dep[n], col[n], lc[m], rc[m], sum[m], mark[m], to[m], nxt[m], head[n];
bool vis[n];
inline int readint()
void add(int u, int v)
void pushdown(int rt)
}void pushup(int rt)
void build(int rt, int l, int r)
int mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(rt);
}void change(int rt, int l, int r, int l, int r, int c)
pushdown(rt);
int mid = l + r >> 1;
if (l <= mid) change(ls, l, mid, l, r, c);
if (r > mid) change(rs, mid + 1, r, l, r, c);
pushup(rt);
}int ask(int rt, int l, int r, int l, int r)
void work(int a, int b, int c)
if (dep[a] < dep[b]) swap(a, b);
change(1, 1, n, id[b], id[a], c);
}int work2(int a, int b)
if (dep[a] < dep[b]) swap(a, b), swap(t1, t2);
t += ask(1, 1, n, id[b], id[a]);
t -= ((t1 == rcol && ~t1) + (t2 == lcol && ~t2));
return t;
}void gao()
for (int i = r; i >= 0; --i)
for (int i = 0; i <= r; ++i)
if (!top[q[i]])
}build(1, 1, n);
}int main()
gao();
while (m--)
else
}return
0;}
bzoj 2243 樹鏈剖分 染色
time limit 20 sec memory limit 512 mb submit 3205 solved 1238 submit status discuss 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段...
bzoj2243 樹鏈剖分 染色
description 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 請你寫乙個程式依次完成這m個操作。input 第一行包含2...
BZOJ 2243 染色 樹鏈剖分
題意 給出一棵樹,每個頂點上有個顏色 c i 有兩種操作 分析 首先樹鏈剖分,下面考慮線段樹部分 我們維護乙個區間的左端點的顏色和右斷點的顏色以及該區間的顏色段數,在加乙個顏色覆蓋標記。在pushup的時候,如果左區間右端點顏色和右區間左端點顏色相同,那麼這段顏色可以合併,合併區間的顏色段數為左右子...