1. 程式人生 > >jzoj5336 【NOIP2017提高A組模擬8.24】提米樹 (dfs序dp,奇異姿勢dp)

jzoj5336 【NOIP2017提高A組模擬8.24】提米樹 (dfs序dp,奇異姿勢dp)

題面

xxx

分析

剪枝的意思就是你可以任意選點作為葉子。(前提是他子樹不選)
比賽的時候有一種60分的n^2 log n做法,就是在dfs序上直接dp.
但是正解比較奇怪,先畫顆樹出來看看,就會發現根到真·葉子的路徑上有且只有一個被選為葉子。於是我們考慮設一種玄學的dp。 令f[i]為在dfs序上,當前最後一個葉子選的是i的最大價值。
想想能更新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 dfsdp奇異姿勢dp

題面 分析 剪枝的意思就是你可以任意選點作為葉子。(前提是他子樹不選) 比賽的時候有一種60分的n^2 log n做法,就是在dfs序上直接dp. 但是正解比較奇怪,先畫顆樹出來看看,就會發現根到真·葉子的路徑上有且只有一個被選為葉子。於是我們考

jzoj5338NOIP2017提高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.15Throw

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.13abcd

哈哈,看這題挺少題解的,就發一份吧 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、將某個數修改。 思考歷程 先看看

JZOJ5353NOIP2017提高A模擬9.9村通網最小生成樹

題目大意: 題目連結:https://jzoj.net/senior/#main/show/5353 為了加快社會主義現代化,建設新農村,農夫約(Farmer Jo)決定給農莊裡每座建築都連上網際網路,方便未來隨時隨地網購農藥。 他的農莊很大,有N 座建築,但地理位置偏僻,網路訊號很

JZOJ5354NOIP2017提高A模擬9.9導彈攔截網路流DP

題目大意: 題目連結:https://jzoj.net/senior/#main/show/5354 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統。 敵國的導彈形成了立體打擊,每個導彈可以抽象成一個三維空間中的點(x; y; z)。攔截系統發射的炮彈也很好地應對了這種情況,每一

jzoj5346NOIP2017提高A模擬9.5NYG的揹包貪心

description solution 考慮貢獻為正的,顯然花費a最少先做,考慮貢獻為負的,可以將ab調轉過來,那顯然花費最少的先做,也就是b最小的先做。 code #include<

jzoj5389NOIP2017提高A模擬9.26解夢

description DYY 很善於解夢,昨晚,他夢見自己來到了一個高度發達的國度。 眾所周知,我們現在有極為常用的三級運算,+、、^。其中,a*b=a+a+a+…+a(b 個a),a^b=a