7 5省隊集訓 tree

2021-07-03 15:16:55 字數 900 閱讀 6014

思路:樹形dp。先求最大值。

令s[x]為x的子樹中葉子節點的數量。

f[x]為到x時 為先手走,先手能取到的值在子樹中排第f[x]小。

g[x]為到x時 為後手走,後手能取到的值在子樹中排第f[x]小。

對f[x],先手應該往哪個子樹走呢?對於x的一棵子樹y,如果進入,那麼最終答案就是這棵子樹中第g[y]小的值,即第s[y]-g[y]大的值,那麼先手只要找到s[y]-g[y]最小的一棵子樹,然後用最大的s[y]-g[y]個編號填好這s[y]-g[y]點,那麼f[i]=s[i]-(s[y]-g[y]);

對於g[x],情況就有些不同了,對於x的一棵子樹y,如果進入,那麼會得到第f[y]小的值,因為現在是求最大,所以這棵子樹中的s[y]-f[y]個點會被最大化以使第f[y]小的值盡量大。最終答案就是所有子樹的第f[y]小值中的最小值。

最小化同理

#include#include#includeusing namespace std;

const int maxn=200010,maxm=400010;

int now[maxn],pre[maxm],son[maxm],n,tot,s[maxn],f[maxn][2],g[maxn][2];

void add(int a,int b)

void dfs(int x)

s[x]=0,g[x][1]=1e9;int s1=0,s2=0;

for (int y=now[x];y;y=pre[y]) dfs(son[y]),s[x]+=s[son[y]];

for (int y=now[x];y;y=pre[y])

g[x][0]=s[x]-s1+1,f[x][1]=s2;

}int main(){

scanf("%d",&n);

for (int i=1,a,b;i

FJOI省隊集訓 florida

省隊成員 大部分 都沒來.像我這種沙茶天天寫寫玄學演算法都能排在榜上面.果然正解寫掛的人遠比暴力拍對的人少啊.陸陸續續會補一些題解。不過有些題太神了可能補不上題解 有n個物品,兩個袋子a和b。若物品i與j放在同乙個袋子裡,那麼代價為t i j 保證t i i 0,t i j t j i 乙個袋子的代...

7 10省隊集訓夢工廠

思路 題面真心長.單調棧維護上凸殼即可 設sum i 為前i道工序的複雜度之和,g i 為第i個快樂最早開始生產的時間。因為我們要保證沒有兩個快樂同時出現在同一道工序,所以 g i g i 1 max sum j f i 1 sum j 1 f i 然後就是像斜率優化的過程了 sum j f i 1...

省隊集訓DAY2

假設我們列舉數列中長度為len的區間,那麼如何判斷兩個數列可以匹配呢?對於提取的數列從小到大排序,從大到小排序,然後兩兩配對,如果所有的都滿足 h 那麼就可以匹配。應該算是貪心吧。這樣做的時間複雜度是o n le n loglen 還是上面的思想,我們如何快速判斷呢?假設我們確定了提取出的區間數列,...