1. 程式人生 > 遊戲 >《紅至日2:終結者》迎來更新 新增終結者職業

《紅至日2:終結者》迎來更新 新增終結者職業

POI的經典trick:二分+DP,30min左右切了。

Description

給一顆 \(n\) 個節點的樹(\(n \le 3 \times 10^5\)),初始時 \(1\) 號節點被染黑,其餘是白的。

兩個人輪流操作,一開始 B 在 \(1\) 號節點。

每一輪,A 選擇 \(k\) 個點染黑,然後 B 走到一個相鄰節點,

如果 B 當前處於白點則 B 勝,否則當 A 將所有點染為黑點時 A 勝。

求能讓 A 獲勝的最小的 \(k\).

Solution

一看,一棵樹,再一看,求最小,第一反應是樹上DP。

\(f_i\) 表示考慮以 \(i\) 為根的子樹的最小的 \(k\)

不行,是個 OIer 都不會這麼設計。(明顯狀態無法從子樹一個個推到根節點)

仔細地看看題,手元一下樣例。

發現假設 B 從 \(u\) 走到了一個兒子 \(v\),那麼決策就只和以 \(v\) 為根的子樹有關係,其他的分支就沒必要考慮了。

再細一點,可以知道,每一步只需要關注下一層(兒子節點)就行了,子樹的話一層層就推下來了。

現在把 \(k\) 再壓進狀態裡面方便列舉。

那麼設 \(f_{k,i}\) 表示當前每一次可以塗 \(k\) 個點的時候, \(i\) 的兒子還需要塗多少次來讓所有兒子都變黑。

從葉子節點開始層層上推,如果 \(f_{k,1} \le 0\) 的話那麼 \(k\)

就是可行的。

DP 完之後從 \(1\) 開始找到所有可能中最小的 \(k\) 即可。

這時候,你看到了 \(n=3\times 10^5\) ,真不幸,你的做法被卡了!

考慮怎麼優化。

設想,假設你 \(k=3\) 就能滿足條件,那 \(k=4,5,6...\) 有必要出現嗎?

擴充套件一下就是,所有 \(f_{k,1}<0\) 的情況都可以歸類到 \(f_{k,1}=0\)。(不歸類會炸——)

所以你發現 \(k\) 具有單調性,而且其實正常做法不好求,那麼就可以掏出二分了!

(順便 \(f\) 的第一維 \(k\) 就不用了,空間複雜度優秀)

我們在值域 \([1,n+1]\) 上二分,每一次 check 的時候 DP 一下看 \(f_1\)

是否為 \(0\) 即可。

狀態就是 : \(f_u\) 表示 \(u\) 的所有兒子在當前的 \(k=mid\) 的情況下還需要塗多少次。

方程也很簡單: \(f_u=tot_{son}+\sum f_v - k,(v\in \text{Son(u)})\)\(tot_{son}\) 是兒子個數。

Code:


#include<bits/stdc++.h>
using namespace std;

#define special if(n==1) return puts("0"),0;
// n=1 要特判!
const int si=3e5+10;
struct Tree{
	int ver,head,Next;
}e[si<<1];
int cnt=0;
void add(int u,int v){
	e[++cnt].ver=v,e[cnt].Next=e[u].head;
	e[u].head=cnt;
}

int n,k;
int f[si];
void dp(int u,int fa){
	int son=0;
	for(register int i=e[u].head;i;i=e[i].Next){
		int v=e[i].ver;
		if(v==fa) continue;
		dp(v,u),son+=f[v],son++;
	}
	son-=k,f[u]=son;
	if(f[u]<0) f[u]=0;
	return;
}
bool check(int mid){
	k=mid,dp(1,0);
	return f[1]==0;
}

int main(){
	scanf("%d",&n);special;
	for(register int i=1;i<n;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v),add(v,u);
	}
	int l=1,r=n+1,ans;
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid)) r=mid,ans=mid;
		else l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

本文來自部落格園,作者:black_trees,轉載請註明原文連結:https://www.cnblogs.com/BTeqwq/p/p3554.html