time limit: 20 sec memory limit: 512 mb
submit: 7971 solved: 2990
[submit][status][discuss]
給定一棵有
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]之間。
做了幾道普通的樹鏈剖分維護邊權、點權,查詢路徑的題目,感覺並沒有什麼特點,然而這題比較有意思,求路徑上連續顏色有幾段,顯然用線段樹的話只要維護當前區間最左和最右的顏色,左右子區間即可推出父區間的答案:左邊段數+右邊段數-(左區間右端點顏色==右區間左端點顏色)。然後統計的時候也要利用這個思想——線段樹的query與樹鏈剖分中記錄u與v上公升區間段數的同時也與u、v最後上公升的區間最左端點顏色比較得到答案。
**:
#include using namespace std;#define inf 0x3f3f3f3f
#define lc(x) (x<<1)
#define rc(x) ((x<<1)+1)
#define mid(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define clr(arr,val) memset(arr,val,sizeof(arr))
#define fast_io ios::sync_with_stdio(false);cin.tie(0);
typedef pairpii;
typedef long long ll;
const double pi = acos(-1.0);
const int n = 100010;
struct seg
;struct edge
edge(int _to, int _nxt): to(_to), nxt(_nxt) {}
};edge e[n << 1];
seg t[n << 2];
int head[n], tot;
int sz[n], fa[n], son[n], top[n], dep[n], idx[n], ts;
int arr[n];
int rc, lc;
void init()
void add(int s, int t)
void dfs1(int u, int f, int d)
}}void dfs2(int u, int tp)
}void pushup(int k)
void pushdown(int k)
void build(int k, int l, int r)
void update(int k, int l, int r, int c)
else
pushup(k);
}}int query(int k, int l, int r, int l, int r)
}int find(int u, int v)
ret += query(1, idx[tu], idx[u], idx[tu], idx[u]);
if (rc == last_u)
--ret;
last_u = lc;
u = fa[tu];
tu = top[u];
}if (dep[u] > dep[v])
ret += query(1, idx[u], idx[v], idx[u], idx[v]);
if (lc == last_u)
--ret;
if (rc == last_v)
--ret;
return ret;
}void solve(int u, int v, int c)
update(1, idx[tu], idx[u], c);
u = fa[tu];
tu = top[u];
}if (dep[u] > dep[v])
swap(u, v);
update(1, idx[u], idx[v], c);
}int main(void)
dfs1(1, 0, 1);
dfs2(1, 1);
build(1, 1, n);
for (i = 1; i <= n; ++i)
update(1, idx[i], idx[i], arr[i]);
while (m--)
else}}
return 0;
}
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路徑上的顏色段...
bzoj2243 樹鏈剖分 染色
description 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 請你寫乙個程式依次完成這m個操作。input 第一行包含2...