題意:給定一棵樹每條邊都帶有權值,給定 m 個詢問查詢 u 和 v 的路徑上權值小於等於 w 的邊的個數
思路:先拆點將邊權變為點權,可以離線來做。將點權小於當前詢問權值的點,更新到線段樹上,然後在查詢路徑上出現過的點的數量。(大於詢問權值的點,還沒更新上去)
#include .h>
#define ll long
long
#define ls (rt<<1)
#define rs (rt<<1|
1)using namespace std;
const
int maxn=
2e5+
10,mod=
1e9+7;
int head[maxn]
,cnt;
struct edge
edges[maxn<<1]
;void
add(
int u,
int v)
struct opt
}e[maxn]
,opt[maxn]
;int n,m;
int num[maxn]
,depth[maxn]
,fa[maxn]
,son[maxn]
;int start[maxn]
,top[maxn]
,times;
int st[maxn<<2]
;void
dfs1
(int u)
}void
dfs2
(int u,
int x)
}void
update
(int rt,
int p,
int l,
int r)
int mid=
(l+r)
>>1;
if(p<=mid)
update
(ls,p,l,mid);if
(p>mid)
update
(rs,p,mid+
1,r)
; st[rt]
=st[ls]
+st[rs];}
intquery
(int rt,
int l,
int r,
int l,
int r)
intqpath
(int u,
int v)
if(depth[u]
>depth[v]
)swap
(u,v)
; ans+=
query(1
,start[u]
,start[v],1
,n);
return ans;
}int ans[maxn]
;int
main()
;}for(
int i=
1;i<=m;
++i);}
sort
(e+1
,e+1
+n-1);
sort
(opt+
1,opt+
1+m)
;int nn=n-1;
n=tot;
dfs1(1
);dfs2(1
,1);
int p=1;
for(
int i=
1;i<=m;
++i)
for(
int i=
1;i<=m;
++i)
printf
("%d\n"
,ans[i]);
return0;
}
也可以用樹剖+主席樹來做,邊權下推成點權。將按dfs序訪問到的權值,更新到主席樹上,對於每次詢問 u,v,可以得到很多重鏈: top
[u
]top[u]
top[u]
和 uu
u,它們對應的時間序為 sta
rt[t
op[u
]]
start[top[u]]
start[
top[
u]] 和 sta
rt[u
]start[u]
start[
u],也就對應主席樹兩個版本sta
rt[t
op[u
]]−1
start[top[u]]-1
start[
top[
u]]−
1 和 sta
rt[u
]start[u]
start[
u],在這兩個版本之間查詢找 小於等於 k 的數即可。
#include .h>
using namespace std;
const
int maxn=
1e5+10;
int head[maxn]
,cnt;
struct edge
edges[maxn<<1]
;void
add(
int u,
int v,
int w)
struct opt
opt[maxn]
;int n,m;
vector<
int>
allw;
int total,wt[maxn]
,ww[maxn]
;int depth[maxn]
,num[maxn]
,fa[maxn]
,son[maxn]
;int start[maxn]
,top[maxn]
,times;
int st[maxn*40]
,root[maxn]
,ls[maxn*40]
,rs[maxn*40]
,no;
void
dfs1
(int u)
}void
dfs2
(int u,
int x)
}int
build
(int l,
int r)
intupdate
(int pre,
int l,
int r,
int p)
intquery
(int pre,
int now,
int l,
int r,
int l,
int r)
intqpath
(int u,
int v,
int p)
if(depth[u]
>depth[v]
)swap
(u,v)
; ans+=
query
(root[start[u]
],root[start[v]],
1,p,
1,total)
;return ans;
}int
main()
for(
int i=
1;i<=m;
++i)
; allw.
push_back
(w);
}sort
(allw.
begin()
,allw.
end())
; allw.
resize
(unique
(allw.
begin()
,allw.
end())
-allw.
begin()
);dfs1(1
);dfs2(1
,1);
total=allw.
size()
; root[0]
=build(1
,total)
;for
(int i=
1;i<=n;
++i)
for(
int i=
1;i<=m;
++i)
return0;
}/*3 21 3 2
1 2 7
2 3 4
2 3 7
*/
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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個。方法一 我是...
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個。方法一 我是...