time limit: 20 sec memory limit: 512 mb
submit: 2492 solved: 960 [
submit][
status]
給定一棵有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 5 3
1 2數n<=10^5,運算元m<=10^5,所有的顏色c為整數且在[0, 10^9]之間。
這個題唯一不太好處理的就是分段處理的時候要看兩段連線的地方的顏色是不是一樣,再加乙個查詢看當前的端點跟他的父親節點是不是顏色一樣就行了
#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
const int maxn=100100;
struct edge
edge[maxn*2];
int n,q;
int a[maxn];
int head[maxn],tot;
int top[maxn];
int w[maxn];
int fw[maxn];
int deep[maxn];
int son[maxn];
int num[maxn];
int fa[maxn];
int pos;
void init()
void add_edge(int u,int v)
void dfs1(int u,int pre,int d)
void pushup(int o)
void pushdown(int o)
}void update(int o,int l,int r,int q1,int q2,int val)
pushdown(o);
int mid=(l+r)>>1;
if(q1<=mid)update(o<<1,l,mid,q1,q2,val);
if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,val);
pushup(o);
}int query(int o,int l,int r,int q1,int q2)
int query2(int o,int l,int r,int pos)
}tree;
void change(int a,int b,int c)
int query(int a,int b)
int main()
{ while(scanf("%d%d",&n,&q)!=eof)
{for(int i=1;i<=n;i++)scanf("%d",&a[i]);
init();
int u,v;
for(int i=1;i
BZOJ 2243 樹鏈剖分
題意 中文題目 思路 樹鏈剖分。首先考慮求區間顏色段數的問題,我們可以用線段樹維護 區間左右端點 st,ed 區間顏色段數 val 懶惰標記 lazy 是否整個區間被染成同一種顏色 區間左右端點的顏色 lcolor,rcolor 然後在查詢的時候如果當前區間的左子樹的右端點的顏色等於右子樹的左端點的...
bzoj 2243 染色 樹鏈剖分
首先這是個挺裸的題,由於太久沒寫剖分導致調了好久,前天調了一下午,一直查不到錯 昨晚在看春晚的時候突然靈機一動,發現合併的時候出了問題,開電腦把它a掉了 感覺自己也蠻拼的給定 一棵有n 個節點的 無根樹和 m個操作 操作有 2類 1 將節點a 到節點b 路徑上所 有點都染 成顏色c 2 詢問節點a ...
bzoj 2243 樹鏈剖分 染色
time limit 20 sec memory limit 512 mb submit 3205 solved 1238 submit status discuss 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段...