題目鏈結
線段樹維護左端顏色,右端顏色,顏色段數量。
合併的時候看左子樹的右端顏色是不是等於右子樹的左端顏色,如果等於那麼顏色段數量要-1s
然後在樹剖跳鏈的時候搞同樣的操作qwq
然後就沒有然後了
#include#include#include
#include
#include
#define maxn 500000
#define left (rt<<1)
#define right (rt<<1|1)
#define mid ((l+r)>>1)
#define lson l,mid,left
#define rson mid+1,r,right
using
namespace
std;
inline
long
long
read()
while
(isdigit(ch))
return num*f;
}int
n,m;
int tag[maxn*2
];int
deep[maxn];
intdfn[maxn],id;
intback[maxn];
intq[maxn];
intson[maxn];
inttop[maxn];
intfather[maxn];
intsize[maxn];
struct
edgeedge[maxn*2
];int
head[maxn],num;
inline
void add(int
from,int
to);
head[
from]=num;
}struct
node;
if(rcol==a.lcol) ans.ncol--;
return
ans;
}}tree[maxn*2
];inline
void pushup(int
rt)inline
void pushdown(int
rt)void build(int l,int r,int
rt);
return
; }
build(lson);
build(rson);
pushup(rt);
}void update(int
from,int to,int num,int l,int r,int
rt);
tag[rt]=num;
return
; }
pushdown(rt);
if(from
<=mid) update(from
,to,num,lson);
if(to>mid) update(from
,to,num,rson);
pushup(rt);
return;}
int query(int
from,int to,int l,int r,int
rt)int qucol(int o,int l,int r,int
rt)void findfs(int x,int
fa)}
void unidfs(int x,int
top)
}void uplink(int
from,int to,int
num)
if(deep[from]>deep[to]) swap(from
,to);
update(dfn[
from],dfn[to],num,1,n,1);}
int qulink(int
from,int
to)
if(deep[from]>deep[to]) swap(from
,to);
ans+=query(dfn[from],dfn[to],1,n,1
);
return
ans;
}int
main()
findfs(
1,1);
unidfs(
1,1);
build(
1,n,1
);
for(int i=1;i<=m;++i)
}return0;
}
Luogu P2486 染色(樹鏈剖分 線段樹)
不妨採取重鏈剖分的方式把路徑剖成區間,然後用線段樹維護,考慮如何合併乙個區間 struct node seg n 2 int col n 2 inline node merge const node lc,const node rc if lc.rg rc.lf ret.tot return ret...
染色 樹鏈剖分
先樹剖,然後再線段樹維護 考慮對每個節點維護 n um numnu m值 表示當前區間顏色段數量 l clc lc值 表示當前區間最左端的顏色 r crc rc值 表示當前區間最右端的顏色 合併時,如果左兒子的rc rc rc 右兒子的lclc lc,那麼合併後父節點的num numnu m值還要減...
可愛的樹鏈剖分(染色)
這道題 就是 一道 普通的 樹鏈剖分 線段樹覆蓋 注意一下兩個線段樹合併的時候 如果 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 相當於這兩個線段樹的相鄰的數字數相同的 那麼合併...