先樹剖,然後再線段樹維護
考慮對每個節點維護
n um
numnu
m值:表示當前區間顏色段數量
l clc
lc值:表示當前區間最左端的顏色
r crc
rc值:表示當前區間最右端的顏色
合併時,如果左兒子的rc=
=rc==
rc==
右兒子的lclc
lc,那麼合併後父節點的num
numnu
m值還要減一;
查詢時同樣要注意,參見**
#include
#define m 200009
using
namespace std;
int nxt[m]
,to[m]
,first[m]
,tot,n,m,cnt,lc,rc;
int idx[m]
,num[m]
,top[m]
,dep[m]
,f[m]
,a[m]
,size[m]
,son[m]
;struct treetr[m*4]
;int
read()
for(
;isdigit
(ch)
;ch=
getchar()
) re=
(re<<3)
+(re<<1)
+ch-
'0';
return re*f;
}void
add(
int x,
int y)
void
dfs1
(int u,
int fa)
}void
dfs2
(int u,
int tp)
void
pushup
(int k)
void
build
(int k,
int l,
int r)
int mid=
(l+r)
>>1;
build
(k<<
1,l,mid)
;build
(k<<1|
1,mid+
1,r)
;pushup
(k);
}void
change
(int k,
int val)
void
pushdown
(int k)
}void
modify
(int k,
int l,
int r,
int val)
intquery
(int k,
int l,
int r)
void
update
(int x,
int y,
int z)
if(dep[x]
)swap
(x,y)
;modify(1
,num[y]
,num[x]
,z);
}int
solve
(int x,
int y)
if(dep[x]
)swap
(x,y)
,swap
(vis1,vis2)
; ans+
=query(1
,num[y]
,num[x]);
if(vis1==rc) ans--;if
(vis2==lc) ans--
;return ans;
}//void debug(int k)
intmain()
dfs1(1
,0),
dfs2(1
,1);
build(1
,1,n);
for(
int i=
1;i<=m;i++
)else
printf
("%d\n"
,solve
(x,y));
}return0;
}
1,對於該類區間合併時,左右區間相互影響時,考慮本題分多種情況的做 可愛的樹鏈剖分(染色)
這道題 就是 一道 普通的 樹鏈剖分 線段樹覆蓋 注意一下兩個線段樹合併的時候 如果 lva l no de 1 1 rval nod e 1 lval node 1 1 rval node 1 lval n ode 1 1 rval nod e 1 相當於這兩個線段樹的相鄰的數字數相同的 那麼合併...
bzoj 2243 染色 樹鏈剖分
首先這是個挺裸的題,由於太久沒寫剖分導致調了好久,前天調了一下午,一直查不到錯 昨晚在看春晚的時候突然靈機一動,發現合併的時候出了問題,開電腦把它a掉了 感覺自己也蠻拼的給定 一棵有n 個節點的 無根樹和 m個操作 操作有 2類 1 將節點a 到節點b 路徑上所 有點都染 成顏色c 2 詢問節點a ...
HYSBZ 2243 染色 樹鏈剖分
思路 單點的樹鏈剖分題目.大致的思路與邊問題的樹鏈剖分大同小異.只是在處理相鄰的顏色的計算的時候需要仔細.wa了幾發.這邊就寫一下我處理的思路以及記得起來的wa點.理解樹鏈剖分之後,你會明白,樹鏈剖分是按照路徑兩邊往中間縮.所以我用cu,cv標記兩端的顏色.當需要從u開始搜的時候,我就比對一下該端的...