SDOI2011 染色 樹鏈剖分

2022-04-30 11:48:11 字數 3044 閱讀 1190

輸入格式:

輸出格式:

對於每個詢問操作,輸出一行答案。

輸入樣例#1:

6 52 2 1 2 1 1

1 21 3

2 42 5

2 6q 3 5

c 2 1 1

q 3 5

c 5 1 2

q 3 5

輸出樣例#1:31

怎麼實現建樹操作呢,我們需要兩個陣列s和t,代表當前操作區間的左端點的顏色和右端點的顏色,那麼當遞迴到(l==r)時,將s及t全部賦為當前顏色,並把當前區間不同顏色個數sum賦值為1(因為只有乙個顏色嘛).

code

void build(int node,int l,int r) 

int mid=l+r>>1;

build(node<<1,l,mid);

build(node<<1|1,mid+1,r);

push_up(node,l,r);

}

(**中的push_up函式會在下面講到)修改操作大致和以前一樣,就是當(當前操作區間在修改區間內時),把當前區間的左右端點的顏色都賦值為需要修改的顏色k,個數計為1,並打上懶惰標記code

void update(int node,int l,int r,int left,int right,int k) 

int mid=l+r>>1;

if(lazy[node]) push_down(node,l,r);

if(left <= mid) update(node<<1,l,mid,left,right,k);

if(mid < right) update(node<<1|1,mid+1,r,left,right,k);

push_up(node,l,r);

}

即統計一下當前區間的個數,有個細節要注意,下面我們來分類討論一下

<1> 左區間 123 右區間 221 那麼此段區間顏色總個數應為左區間顏色個數3+右區間個數2=5,這是第一種情況,沒有問題<2>左區間 122 右區間 231 此時此段區間顏色個數應為左區間個數2+右區間顏色個數3-1(中間有連續的顏色2)=4相信大家也發現了,我們在統計個數的時候需要記錄一下t[左區間]是否等於s[右區間],如果等於總個數就要-1

code

inline void push_up(int node,int l,int r)
也沒什麼好說的,大部分一樣,也是要判斷當t[左區間]==s[右區間]時,ans- -code

int check(int node,int l,int r,int left,int right)
這道題是一道好題,既能幫助你理解線段樹又能更好的學習樹鏈剖分,就是比較難調,值得一做

#include#define in(i) (i=read())

using namespace std;

int read()

while(i>='0' && i<='9')

return ans*f;

}const int n=1e5+10;

struct edge e[n*2];

int n,m,len,cnt;

int dep[n],dfn[n],son[n],size[n],fa[n],head[n],top[n],col[n];

int sum[n*4],s[n*4],t[n*4],c[n*4],lazy[n*4];

void add(int a,int b)

void dfs1(int u)

}}void dfs2(int u,int t)

}inline void push_up(int node,int l,int r)

inline void push_down(int node,int l,int r)

void build(int node,int l,int r)

int mid=l+r>>1;

build(node<<1,l,mid);

build(node<<1|1,mid+1,r);

push_up(node,l,r);

}void update(int node,int l,int r,int left,int right,int k)

int mid=l+r>>1;

if(lazy[node]) push_down(node,l,r);

if(left <= mid) update(node<<1,l,mid,left,right,k);

if(mid < right) update(node<<1|1,mid+1,r,left,right,k);

push_up(node,l,r);

}int check(int node,int l,int r,int left,int right)

int main()

else

}return 0;

}

SDOI 2011 染色 樹鏈剖分

題意 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點n路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 n,m 100000 思路 樹的形態沒有改變,用樹鏈剖分維護即可。pre1,...

SDOI2011 染色 樹鏈剖分

題目鏈結 有一棵n個節點的樹,每個節點有顏色,支援兩種操作 樹上的鏈操作擺明了要用樹鏈剖分.用線段樹來維護資訊.線段樹的每個節點需要儲存,區間的顏色數量,以及區間左端點的顏色和右端點的顏色.以下是線段樹中特殊操作 先把左右兒子的顏色段數加起來.如果左兒子的右端點和右兒子的左端點是同一種顏色,那麼顏色...

SDOI2011 染色 題解

題目大意 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 思路 樹剖之後,維護其兩端的顏色 答案和標記即可。include include define n 100001 using...