对于 k=1 k = 1 ,可以直接树形DP求出答案。
对于 k>1 k > 1 ,显然 maxdepth<logkn m a x d e p t h < log k n 。设 dpi,j d p i , j 表示 i i 号点, depth d e p t h 为 j j 时最大的 k k ,那么状态数是 O(nlogn) O ( n log n ) 的。
如果我们求出了 dpi,j d p i , j ,由于随着 k k 的减小,每个点的 depth d e p t h 肯定是单调不降的,所以可以把每个 k k 要更新哪些点记下来,从大到小枚举 k k ,更新相关点的 depth d e p t h 。由于一个点最多只会被更新 maxdepth m a x d e p t h 次,这部分的复杂度为 O(nlogn) O ( n log n ) 。
然后考虑怎么求 dpx,i d p x , i 。将所有儿子按照 dpv,i−1 d p v , i − 1 从大到小排序,如果第 k k 大的值 ≥k ≥ k , dpx,i d p x , i 就可以取到 k k 。从大到小枚举 k k ,找到就退出。复杂度为 n∑ni=2login=O(nlogn) n ∑ i = 2 n log i n = O ( n log n ) 。
#include
using namespace std;
char nc() {
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
void Read(int& x) {
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define fi first
#define se second
const int N=300010;
const int M=19;
typedef pair<int,int> abcd;
typedef long long ll;
int n,m,x,y;
int t[N<<1],nx[N<<1],h[N],num;
int f[N],c[N],dp[N][M];
int a[N],l,cur[N];
vector g[N];
ll Res,Ans;
void Add(int x,int y) {
t[++num]=y;nx[num]=h[x];h[x]=num;
}
bool Cmp(int x,int y) {
return x>y;
}
void Dfs(int x,int y) {
dp[x][1]=n;f[x]=y;
for(int i=h[x];i;i=nx[i])
if(t[i]!=y) Dfs(t[i],x),c[x]=max(c[x],c[t[i]]);
for(int j=2;j0;
for(int i=h[x];i;i=nx[i])
if(t[i]!=y&&dp[t[i]][j-1]) a[++l]=dp[t[i]][j-1];
sort(a+1,a+l+1,Cmp);
for(int k=l;k>1;k--)
if(a[k]>=k) {
dp[x][j]=k;
break;
}
if(dp[x][j]) g[dp[x][j]].push_back(abcd(x,j));
}
Ans+=++c[x];
}
void Update(int x,int y) {
while(x) {
if(cur[x]>=y) break;
Res+=y-cur[x];
cur[x]=y;
x=f[x];
}
}
int main() {
Read(n);
for(int i=1;i1,0);
for(int i=1;i<=n;i++) cur[i]=1;
Res=n;
for(int k=n;k>1;k--) {
for(int j=0;jcout<return 0;
}