虛樹板題一道。。。
個人覺得這題比 「消耗戰」更適合練板子(樹形dp更為簡單)
說正解。
注意到∑∣p
∣≤2e
6\sum |p|\le2e6
∑∣p∣≤2
e6,這提示我們建一顆虛樹。
建好後,2和3問就是求乙個樹上最短路,最長路,不再贅述。
簡單說一下1,我們對於每一條邊統計有多少點對經過它。
具體的,樹形dp的時候算出,即為siz
[son
]∗(t
ot−s
iz[s
on
)siz[son]*(tot-siz[son)
siz[so
n]∗(
tot−
siz[
son)
。
#include
using
namespace std;
#define sf scanf
#define ri register int
#define in red()
#define gc getchar()
#define ll long long
#define cs const
inline
intred()
cs int n=
1e6+10;
cs ll inf=
1e14
;int head[n]
,to[n<<1]
,nxt[n<<1]
,cnt=
0,dep[n]
,n,m,dfn[n]
,tot;
inline
void
adde
(int u,
int v)
namespace sp}}
inline
void
ddfs1
(int u,
int f)
}inline
intlca
(int x,
int y)
return dep[x]
? x : y;
}inline
void
init()
}using sp::lca;
using sp::init;
inline
bool
cmp(cs int
&a,cs int
&b)typedef pair<
int,
int> pi;
#define fi first
#define se second
vector g[n]
;inline
void
link
(int x,
int y)
ll maxn,siz[n]
,mx[n]
,mn[n]
,ans1,ans2,ans3;
bool vis[n]
;//vis標記打上,清掉
void
dfs2
(int u,
int fa)
g[u]
.clear()
;}inline
void
work
(vector<
int>
&f)int l=
lca(
*stk.
rbegin()
,f[i]);
while
(stk.
size()
>
1&&dfn[*(
--(--stk.
end())
)]>=dfn[l]
)link(*
(--(--stk.
end())
),*stk.
rbegin()
),stk.
pop_back()
;if((
*stk.
rbegin()
)^l)
link
(l,*stk.
rbegin()
),stk.
pop_back()
,stk.
push_back
(l);
stk.
push_back
(f[i]);
}while
(stk.
size()
>1)
link(*
(--(--stk.
end())
),*stk.
rbegin()
),stk.
pop_back()
; maxn=f.
size()
; ans1=
0;ans2=inf;ans3=
-inf;
dfs2
(*stk.
begin()
,0);
cout<' '<' '<'\n';}
vector<
int> cot;
signed
main()
return0;
}
P4103 HEOI2014 大工程 (虛樹)
觀察資料範圍是跟k有關的,因此我們考慮建立虛樹,對於維護三個值 總和就是常規的按每條路左右兩邊點數算貢獻,注意是特殊點的數量 之後我們維護mi i mx i 表示對於當前點,子樹中離他最近的特殊點在哪 includeusing namespace std typedef long long ll t...
P4103 HEOI2014 大工程 虛樹
戳這裡 虛樹板子題 首先有乙個 o qn 的暴力,就是對於每一次詢問,o n 的樹上 dp 我們統計一下每乙個點,它的子樹內離它最近 遠的關鍵點的距離,已經關鍵點的個數 對於第乙個詢問等價於 sum dep x dep y sum2 times dep lca 我們 dp 的時候順便統計一下每乙個點...
HEOI2014 大工程 虛樹 樹形DP
還不錯,就是理解題意的時候理解的久了一些。題目中的距離實際上是每兩個點在原樹上的距離,而新建的結點是不會影響的,所以總的距離和是原樹上任意兩點的距離之和 最短距離呢,實際上就是最短邊權了 最長距離,實際上就是新構成虛樹上樹的直徑了,當然得是有效點的。所以,構建虛樹,然後再進行乙個樹形dp就可以了。i...