jzoj5336 【NOIP2017提高A組模擬8.24】提米樹 (dfs序dp,奇異姿勢dp)
題面
分析
剪枝的意思就是你可以任意選點作為葉子。(前提是他子樹不選)
比賽的時候有一種60分的n^2 log n做法,就是在dfs序上直接dp.
但是正解比較奇怪,先畫顆樹出來看看,就會發現根到真·葉子的路徑上有且只有一個被選為葉子。於是我們考慮設一種玄學的dp。 令
想想能更新i的點有哪些。 由於要保證每條到葉子的路徑上都有選中的,那麼當前狀態要麼沒有意義( 選他的祖先 ),要麼就從相鄰的葉子節點到二者lca (不含)這條路徑上的點更新過來。 (看不懂的就看圖吧)
這樣每次列舉兩個相鄰葉子,然後暴力列舉從哪個綠點轉移的話是O(n^2)的。
沒有被轉移到的點價值就是本身。 (因為他不需要接盤,只選自己就行)
在優化之前,先證明一個結論: 相鄰葉子節點的路徑長度(也就是點數-1)不會超過2n.
考慮一條邊會被選到多少次,當然最多兩次了,子樹外到內 與 內到外各一次。子樹內都選不到他。
這樣從上到下更新要更新的點,lca~當前要更新的點 的路徑mx當然是遞增的,然後左邊決策集合中的mx也是遞增的,維護一個指標now表示當前決策集合(按深度排序,感受一下) 1..now-1是用自己那邊的mx,然後now..lca是用 lca~當前要更新的點上的mx。
這樣維護一個字首和+字尾和,快速計算一下兩部分的最優值就可以O(n)做了。 (細節比較多但為什麼有大佬能打進1000byte)
Demo
#include <cstdio>
#include <iostream>
#include <cstring>
#define max(a,b) ((a)<(b)?(b):(a))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=1e5+10,INF=2e9;
int final[N],nex[N],to[N],tot,dep[N];
int n,a[N];
int fa[N],ch[N];
int f[N];
int s[N],td[N],pre[N],sufmxa[N],sufmxf[N];
int tmp[N];
void link(int x,int y) {to[++tot]=y, nex[tot]=final[x], final[x]=tot;}
void dfs(int x) {
dep[x]=dep[fa[x]]+1;
if (!final[x]) ch[++ch[0]]=x; else
for (int i=final[x]; i; i=nex[i]) fa[to[i]]=x, dfs(to[i]);
}
int init(int x,int y) {
int tx=x,ty=y,g=0;
s[0]=td[0]=0;
while (dep[ty]>dep[x]) td[++td[0]]=ty,ty=fa[ty];
while (dep[tx]>dep[y]) {
if (f[tx]==f[0]) f[tx]=a[tx];
s[++s[0]]=tx;
tx=fa[tx];
}
while (tx!=ty) {
if (f[tx]==f[0]) f[tx]=a[tx];
td[++td[0]]=ty, s[++s[0]]=tx;
tx=fa[tx],ty=fa[ty];
}
s[++s[0]]=g=tx;
pre[0]=sufmxa[s[0]]=sufmxf[s[0]]=-INF;
if (f[g]==f[0]) f[g]=a[g];
for (int i=s[0]-1; i; i--) {
sufmxf[i]=max(sufmxf[i+1],f[s[i]]); //max f[a..g]
sufmxa[i]=max(sufmxa[i+1],a[s[i+1]]);//max a[fa[a]..g]
}
for (int i=1; i<s[0]; i++) pre[i]=max(pre[i-1],f[s[i]] - sufmxa[i]); //max ans[1..i]
return g;
}
int main() {
freopen("3.in","r",stdin);
// freopen("3.out","w",stdout);
cin>>n;
for (int i=1; i<=n; i++) {
int k=0;
scanf("%d %d",&a[i],&tmp[0]);
for (int j=1; j<=tmp[0]; j++) scanf("%d",&tmp[j]);
for (int j=tmp[0]; j; j--) link(i,tmp[j]);
}
memset(f,128,sizeof f);
dfs(1);
for (int i=1; i<ch[0]; i++) {
int x=ch[i],y=ch[i+1],g=init(x,y),now=s[0],rmx=0;
for (int d,j=td[0]; j; j--) {
d=td[j], rmx=max(rmx,a[fa[d]]);
while (now>1 && sufmxa[now-1]<=rmx) now--;
f[d]=max(pre[now-1], sufmxf[now] - rmx)+a[d];
}
}
int ans=0;
for (int i=ch[ch[0]]; i; i=fa[i]) {
if (f[i]==f[0]) f[i]=a[i];
ans=max(ans,f[i]);
}
printf("%d\n",ans);
}
相關推薦
jzoj5336 【NOIP2017提高A組模擬8.24】提米樹 (dfs序dp,奇異姿勢dp)
題面 分析 剪枝的意思就是你可以任意選點作為葉子。(前提是他子樹不選) 比賽的時候有一種60分的n^2 log n做法,就是在dfs序上直接dp. 但是正解比較奇怪,先畫顆樹出來看看,就會發現根到真·葉子的路徑上有且只有一個被選為葉子。於是我們考
【jzoj5338】【NOIP2017提高A組模擬8.25】【影子】【點分治】
description 有必要說明一下,下面的點分治在菊花圖上會tle。 solution 直接點分治,維護點權最小值和邊權和,按點權最小值排序,兩個指標維護一下最大值即可。 code #include<set> #
JZOJ5372.【NOIP2017提高A組模擬9.17】貓鏈表+貪心+堆優化
margin targe sga gin bt5 ie8 usm shu auc x壹鼐順51比http://shequ.docin.com/txqq_cb3d1e346f 惹M3桓7O2疽http://www.docin.com/app/user/userinfo?use
【NOIP2016提高A組模擬8.14】瘋狂的火神
noip 表示 for algorithm can 並且 code 但是 不同 題目 火神為了檢驗zone的力量,他決定單挑n個人。 由於火神訓練時間有限,最多只有t分鐘,所以他可以選擇一部分人來單挑,由於有麗子的幫助,他得到了每個人特定的價值,每個人的價值由一個三元組(a
【NOIP2016提高A組模擬8.17】(雅禮聯考day1)Value
我們 mat csdn names 分享圖片 提高 struct ring math 題目 分析 易證,最優的答案一定是按\(w_i\)從小到大放。 我們考慮dp, 先將w從小到大排個序,再設\(f_{i,j}\)表示當前做到第i個物品,已選擇了j個物品的最大值。轉移就是
【NOIP2016提高A組模擬8.17】(雅禮聯考day1)Matrix
Go using return 分享圖片 pac IT 出發點 img scanf 題目 分析 假設,我們從\(F_{i,2}\)出發,那麽對\(F_{n,n}\)的貢獻就是\(某個系數乘以a^{n-i}b^{n-1}r_i\); 同理,如果從\(F_{2,i}\)出發,
【NOIP2016提高A組模擬8.15】Throw
tin sca begin spa 元組 int clu AI pac 題目 分析 首先對於一個狀態(a,b,c),假定a<=b<=c; 現在考慮一下這個狀態,的轉移方案: \[1,中間向兩邊跳(a,b,c)-->(a*2-b,a,c)、(a,b,c)-
【NOIP2016提高A組模擬8.17】(雅禮聯考day1)Binary
cstring names 分享圖片 img ace queue lin print mat 題目 分析 首先每個數對\(2^i\)取模。也就是把每個數的第i位以後刪去。 把它們放進樹狀數組裏面。 那麽當查詢操作, 答案就位於區間\([2^i-x,2^{i-1}-1-x]
JZOJ 100027. 【NOIP2017提高A組模擬7.7】表示式
JZOJ 100027. 【NOIP2017提高A組模擬7.7】表示式 題目 Description Input 一行兩個整數k,p。 Output 一行一個整數表示答案。 Sample Input 1 3 Sample Output 6 D
jzoj100026. 【NOIP2017提高A組模擬7.7】圖(倍增)
100026. 【NOIP2017提高A組模擬7.7】圖 Description 有一個n個點n條邊的有向圖,每條邊為<i,f(i),w(i)>,意思是i指向f(i)的邊權為w(i)的邊,現
jzoj100027. 【NOIP2017提高A組模擬7.7】表示式
Description Input 一行兩個整數k,p。 Output 一行一個整數表示答案。 Sample Input 1 3 Sample Output 6 Data Constraint 對於2
jzojs 5384. 【NOIP2017提高A組模擬9.23】四維世界
Description 眾所周知,我們常感受的世界是三維的。 Polycarp突然對四維空間產生了興趣,他想對四維空間進行一些研究。但是在此之前,他必須先對三維世界瞭解透徹。 於是Polycarp決定從零維,也就是一個點,開始他的研究。我們把一個點放在三維空間中,Polycarp把這
jzojs 100044. 【NOIP2017提高A組模擬7.13】abcd
哈哈,看這題挺少題解的,就發一份吧 Description Input 輸入檔名為abcd.in。 輸入檔案共 N+1 行。 第 1 行包含1個正整數N。 第 i+1 行包含4個整數a[i],b[i],c[i],d[i]。 Output 輸出
jzojs 100047. 【NOIP2017提高A組模擬7.14】基因變異
Description 21 世紀是生物學的世紀,以遺傳與進化為代表的現代生物理論越來越多的 進入了我們的視野。 如同大家所熟知的,基因是遺傳因子,它記錄了生命的基本構造和效能。 因此生物進化與基因的變異息息相關,考察基因變異的途徑對研究生物學有著 至關重要的作用。現在,讓我們來看這
JZOJ100048 【NOIP2017提高A組模擬7.14】緊急撤離
題目 題目大意 給你一個01矩陣,每次詢問從一個點是否可以走到另一個點。 每次走只能往右或者往下。 思考歷程 這題啊,我想的時候真的是腦洞大開…… 首先,我一眼看下去,既然要詢問是否聯通,那麼能不能求出它們的最短路,看看是不是它們的曼哈頓距離?
JZOJ100045 【NOIP2017提高A組模擬7.13】好數
題目 題目大意 首先有一個定義: 對於一個數,如果和它互質的數可以組成一個等差數列,那麼這個數叫“好數”。 現在給你一個數列,有三種操作: 1、詢問一段區間內的好數的個數。 2、將一段區間內的數分別模一個值。 3、將某個數修改。 思考歷程 先看看
【JZOJ5353】【NOIP2017提高A組模擬9.9】村通網【最小生成樹】
題目大意: 題目連結:https://jzoj.net/senior/#main/show/5353 為了加快社會主義現代化,建設新農村,農夫約(Farmer Jo)決定給農莊裡每座建築都連上網際網路,方便未來隨時隨地網購農藥。 他的農莊很大,有N 座建築,但地理位置偏僻,網路訊號很
【JZOJ5354】【NOIP2017提高A組模擬9.9】導彈攔截【網路流】【DP】
題目大意: 題目連結:https://jzoj.net/senior/#main/show/5354 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統。 敵國的導彈形成了立體打擊,每個導彈可以抽象成一個三維空間中的點(x; y; z)。攔截系統發射的炮彈也很好地應對了這種情況,每一
【jzoj5346】【NOIP2017提高A組模擬9.5】【NYG的揹包】【貪心】
description solution 考慮貢獻為正的,顯然花費a最少先做,考慮貢獻為負的,可以將ab調轉過來,那顯然花費最少的先做,也就是b最小的先做。 code #include<
【jzoj5389】【NOIP2017提高A組模擬9.26】【解夢】
description DYY 很善於解夢,昨晚,他夢見自己來到了一個高度發達的國度。 眾所周知,我們現在有極為常用的三級運算,+、、^。其中,a*b=a+a+a+…+a(b 個a),a^b=a