給定一棵有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#includeusing
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路徑上的顏色段數量 連續相同顏色...