給出乙個01序列,序列中的01會抵消掉,相當於括號匹配。
給出一段區間,進行2種操作:1、求出區間去掉匹配的01後最大的值(另外給出)。2、修改值。
\(n\leq 100000\ m \leq 100000\)
把01當成括號序列匹配一樣進棧,根據此建一棵樹。
那麼01的序列自然會抵消掉,剩下的查詢序列之間就只有3種情況:1111111..000000..11111100000之類
利用樹鏈剖分對樹上進行操作。
#include #include #include using namespace std;
int n, m, cnt, tot;
int op[100001], a[100001], pos[100001];
int head[100001], ver[200001], next[200001];
int fa[100001], dep[100001], size[100001], son[100001], top[100001], seg[100001];
pairv[100001], rev[100001];
void add(int u, int v)
void dfs1(int u)
}void dfs2(int u, int t)
}struct treenode
void build(int type, int p, int l, int r)
int mid = l + r >> 1;
build(type, p << 1, l, mid);
build(type, p << 1 | 1, mid + 1, r);
update(p);
} void modify(int type, int p, int l, int r, int pp, int val)
int mid = l + r >> 1;
if (pp <= mid) modify(type, p << 1, l, mid, pp, val);
else modify(type, p << 1 | 1, mid + 1, r, pp, val);
update(p);
} int find(int p, int l, int r, int l, int r)
}t0, t1;
int query(int type, int x, int y)
if (x == y) return res;
if(dep[x] > dep[y]) swap(x, y);
else type ^= 1;
res = type ? max(res, t1.find(1, 1, cnt, seg[son[x]], seg[y])) : max(res, t0.find(1, 1, cnt, seg[son[x]], seg[y]));
return res;
}int main() else else now = fa[now];
} }dfs1(root);
dfs2(root, root);
t0.build(0, 1, 1, cnt);
t1.build(1, 1, 1, cnt);
for (int x, y, ml; m; m--) else
int px = pos[x], py = pos[y];
if(op[x] == 0) px = fa[px];
if(op[y] == 1) py = fa[py];
printf("%d\n", query(1, px, py));
} }}
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...
SPOJ QTREE2 樹鏈剖分
題意 有一棵n個節點的樹 1 n 10000 n 1條邊,邊的編號為1 n 1,每條邊有乙個權值,要求模擬兩種操作 1 dist a b 求 點a到點b之間的距離 2 kth a b k 求從a出發到b遇到的第k個節點的編號 qtree系列的第二題。求dist就不用說啦,主要是求第k個。方法一 我是...
樹鏈剖分習題 2(提高)
題意 給定一棵樹每條邊都帶有權值,給定 m 個詢問查詢 u 和 v 的路徑上權值小於等於 w 的邊的個數 思路 先拆點將邊權變為點權,可以離線來做。將點權小於當前詢問權值的點,更新到線段樹上,然後在查詢路徑上出現過的點的數量。大於詢問權值的點,還沒更新上去 include h define ll l...