BZOJ2243 SDOI2011 染色 題解

2022-05-16 16:36:11 字數 3071 閱讀 9917

給定一棵有n個節點的無根樹和m個操作,操作有2類:

1、將節點a到節點b路徑上所有點都染成顏色c;

2、詢問節點a到節點b路徑上的顏色段數量(連續相同顏色被認為是同一段),

如「112221」由3段組成:「11」、「222」和「1」。

請你寫乙個程式依次完成這m個操作。

第一行包含2個整數n和m,分別表示節點數和運算元;

第二行包含n個正整數表示n個節點的初始顏色

下面 行每行包含兩個整數x和y,表示x和y之間有一條無向邊。

下面 行每行描述乙個操作:

「c a b c」表示這是乙個染色操作,把節點a到節點b路徑上所有點(包括a和b)都染成顏色c;

「q a b」表示這是乙個詢問操作,詢問節點a到節點b(包括a和b)路徑上的顏色段數量。

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

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 531

2數n<=10^5,運算元m<=10^5,所有的顏色c為整數且在[0, 10^9]之間。

(吐槽一下bzoj,洛谷能過的**bzoj re……後來優化了讀入才ac……坑爹啊)

首先是樹鏈剖分的裸題。點這裡看樹鏈剖分原理。

然後考慮合併區間時候的問題。

我們記錄每個區間的端點顏色,區間個數,當然還有lazy標記。

然後區間合併看相鄰的端點顏色是否一致,如果一致答案就-1。

樹上需要特意查重路徑的頂點和他爸顏色是否一致,如果一致答案就-1。

#include#include

using

namespace

std;

const

int n=100001

;int

read()

while(ch>='

0'&&ch<='

9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();

return w?-x:x;

}struct

nodeedge[

2*n];

struct

treet[

4*n];

int head[n],cnt=0

,n;void add(int u,int

v)int

fa[n],dep[n],size[n],son[n],top[n],pos[n],idx[n];

intval[n];

void dfs1(int

u)

return;}

inttot;

void dfs2(int u,int

anc)

return;}

void

init()

void pushdown(int

a)

return;}

void build(int a,int l,int

r)

int mid=(l+r)>>1

; build(a*2

,l,mid);

build(a*2+1,mid+1

,r);

t[a].lc=t[a*2].lc;t[a].rc=t[a*2+1

].rc;

t[a].num=t[a*2].num+t[a*2+1

].num;

if(t[a*2].rc==t[a*2+1].lc)t[a].num--;

return;}

int query(int a,int l,int r,int l1,int

r1)

int mid=(l+r)>>1

; pushdown(a);

int k1=query(a*2

,l,mid,l1,r1);

int k2=query(a*2+1,mid+1

,r,l1,r1);

if(k1&&k2)

return k1+k2;

}int check(int a,int l,int r,int

k)int pathquery(int u,int

v)

int ans=query(1,1

,n,pos[top[u]],pos[u]);

if(check(1,1,n,pos[top[u]])==check(1,1,n,pos[fa[top[u]]]))ans--;

res+=ans;

u=fa[top[u]];

}if(dep[u]>dep[v])

return res+query(1,1

,n,pos[u],pos[v]);

}void modify(int a,int l,int r,int l1,int r1,int

v)

int mid=(l+r)>>1

; pushdown(a);

modify(a*2

,l,mid,l1,r1,v);

modify(a*2+1,mid+1

,r,l1,r1,v);

t[a].lc=t[a*2].lc;t[a].rc=t[a*2+1

].rc;

t[a].num=t[a*2].num+t[a*2+1

].num;

if(t[a*2].rc==t[a*2+1].lc)t[a].num--;

return;}

void pathmodify(int u,int v,int

c) modify(

1,1,n,pos[top[u]],pos[u],c);

u=fa[top[u]];

}if(dep[u]>dep[v])

modify(

1,1,n,pos[u],pos[v],c);

return;}

intmain()

init();

build(

1,1,n);

while(q--)

else

}return0;

}

Bzoj2243 SDOI2011 染色 樹鏈剖分

一眼就知道是個樹剖 對於線段樹上每個區間,我們維護最左邊的顏色 最右邊的顏色 總顏色段數 合併區間的時候父區間的顏色段數 左右兒子的顏色段數和 左兒子最右邊的顏色是否和有兒子最左邊的顏色相等 然而我寫炸了一上午qaq 指標的線段樹等於號寫成了減號真是看不出來qaq 令人雞凍的 include inc...

BZOJ 2243 染色 動態樹

題意 一棵樹,初始時每個節點有乙個顏色。兩種操作 1 將某條路經上的點的顏色統一修改為某個值 2 統計某條路徑上顏色有多少段?比如11221算3段。思路 splay節點記錄區間的左右兩側的顏色lr,該節點的顏色val以及總的段數以及標記。向上合併時根據左孩子右孩子的lr以及當前節點的val計算當前子...

樹鏈剖分 bzoj2243

time limit 20 sec memory limit 512 mb submit 2492 solved 960 submit status 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色...