題目大意:
在一棵樹中選擇k條不重複的垂直的長度在[l
,r] [l,
r]之間的樹鏈,樹鏈的價值定義為點權的加和,求最大總價值 n≤
500000
n
≤500000
顯然,我們可以列舉每一條符合條件的樹鏈,取前k大的進行選擇——極端o(
n∗n)
o (n
∗n)那麼看這題之前,先考慮乙個較簡單的情形:
在乙個陣列中,找乙個第k大的滿足長度為[l
,r] [l,
r]的子串行n≤
500000
n
≤500000
有點困難。。求最大的就很簡單了——
構造字首和,列舉個終點
i i
,在[i
−r,i
−l]' role="presentation" style="position: relative;">[i−
r,i−
l][i
−r,i
−l]中找出最小值,最後刷最優解s[
i]−m
ins [i
]−mi
n:rmq就可以完美搞定了
我們假設mi
n=s[
t]m in
=s[t
],則t t
將區間[i
−r,i
−l]' role="presentation" style="position: relative;">[i−
r,i−
l][i
−r,i
−l]劃分成兩部分,且顯然以
i i
為終點的次優解min一定在區間[i
−r,t
−1]或
[t+1
,i−l
]' role="presentation" style="position: relative;">[i−
r,t−
1]或[
t+1,
i−l]
[i−r
,t−1
]或[t
+1,i
−l]中——
這個問題顯然與剛才的問題相同
那麼,我們就定義乙個三元組(i
,l,r
) (i,
l,r)
,表示從
i i
往左推l−
−r' role="presentation" style="position: relative;">l−−
rl−−
r個單位,即s[
i]−m
in[i
−r][
i−l]
s [i
]−mi
n[i−
r][i
−l]ps:l,r是否包括該元素自己定義,如上為包含的
每次在堆中取個最大的出來,將區間拆分後再放入堆中,處理k次,最後一次的即為答案 效率o
(3∗n
∗log
+n∗l
og預處
理)o (3
∗n∗l
og+n
∗log
預處理)
#pragma gcc optimize(6)
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=(1e5)+5,log=21;
int n,k,l,r,len;ll s[maxn];
templatet min(t a,t b)
void ask(int x,int l,int r)
struct ff
ff get()
char gt()
int read()
int main();
make();
for(int i=l;i<=n;i++) ask(i,l,min(i,r)),put(((ff)));
while(k--)));
if(ans.x-ans.it+2
<=ans.r) ask(ans.x,ans.x-ans.it+2,ans.r),put(((ff)));
}printf("%lld\n",ans.val);
return
0;}
再回歸正題——這題不就是將這個模型做到樹上嗎?
預處理即為樹上rmq——倍增lca的同時順便帶出來就ok了
然後**神似。。
ps:仍然那句話,是否包括自身——下面**中va
l[x]
[i] val
[x][
i]表示節點
x x
向上推了2j
' role="presentation" style="position: relative;">2j2
j個單位(不包括自身)加上自身的價值的最小值(有點拗口?多讀幾遍就懂了o(∩_∩)o!)
#pragma gcc optimize(6)
#include
#include
#define ll long long
using
namespace
std;
const
int maxn=(5e5)+5,log=21;const ll inf=(ll)1
<<60;
int n,m,rot,l,r,len,dep[maxn],down[maxn],up[maxn][log],pow[maxn];ll p[maxn],ans;
template
t min(t a,t b)
char gt()
int read()
struct ff
ff get()
struct st
}val[maxn][log],now;
st getdata(int x,int l,int r)));
now.id=down[now.id];
}void dfs(int x,int fa)),((st))),up[x][0]=fa,down[fa]=x;
for(int i=1;(1
<1]][i-1],val[x][i]=min(val[x][i-1],val[up[x][i-1]][i-1]);
if(dep[x]>=l) getdata(x,min(l,dep[x]),min(r,dep[x])),put(((ff)));
for(int j=lnk[x];j;j=nxt[j]) dfs(son[j],x);
}int main()
for(int i=1;i<=n;i++) p[i]=read();
m=read(),l=read(),r=read();
for(int i=1;i<=maxn-5;i++) pow[i]=pow[i-1]+((1
<
dep[rot]=1,dfs(rot,0);
while(m--)));
if(dep[k.x]-dep[k.it]+2
<=k.r) getdata(k.x,dep[k.x]-dep[k.it]+2,k.r),put(((ff)));
}printf("%lld\n",ans);
return
0;}
九度Oj題解
一 動態規劃專題 1205 n階樓梯上樓問題 dp i 表示到達i階的方法數,狀態轉移方程 dp i dp i 1 dp i 2 值很大要用long long.1451 不容易系列之一 dp i 表示總共i個數時的錯排方案數,狀態轉移方程 dp i i 1 dp i 1 i 2 dp i 2 142...
北大oj題解 2255
根據二叉樹的前序和中序寫出後序 二叉樹比較適合用遞迴的方法,按照需要分別處理根節點和左右子樹,前序串的特點是第乙個字元代表的都是該樹的根節點,中序串的特點是左右子樹分別位於根節點的兩側 同理,後序串的特點是最後乙個字元代表根節點 先處理左右子樹最後訪問根節點可得後序串。include include...
學軍OJ題解 1179 約會
學軍oj,題號1179,鏈結 也可以到 小藍準備去和小紅約會,小藍和小紅居住在乙個平面直角座標系中,小藍的家在 0,0 位置,小紅的家在 a,b 位置,小藍每一步可以往上下左右中的任意乙個方向移動乙個單位,換句話說,他可以從 x,y 走 到 x 1,y x 1,y x,y 1 x,y 1 中的乙個位...