洛谷

Codeforces


根号分治真是妙啊。


思路

考虑对于单独的一个\(k\)如何计算答案。

与“赛道修建”非常相似,但那题要求边,这题要求点,所以更加简单。

在每一个点贪心地把子树升上来的两条最长的链拼在一起,能组就组,否则把最长链往上送,复杂度\(O(n)\)。

那么多个\(k\)怎么办呢?

分析一波,\(k<\sqrt{n}\)时可以暴力计算,而\(k>\sqrt{n}\)时\(ans_k\leq \lfloor \frac{n}{k}\rfloor\),只有\(\sqrt{n}​\)种取值。

显然\(ans\)单调不增,所以可以二分边界,复杂度\(O(n\sqrt{n}\log n)\)。

把界限调为\(\sqrt{n\log n}\)后复杂度可以优化至\(O(n\sqrt{n\log n})\)。

然而我这么写T掉了……

发现网上还有一种整体二分的写法,不知为何跑的飞快……只能改成整体二分了……


代码

注释掉的是根号分治的代码,求找错\(Q\omega Q\)

#include<bits/stdc++.h>
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 101010
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename T>inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
template<typename T>inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; int n;
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
edge[++ecnt]=(hh){t,head[f]};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t]};
head[t]=ecnt;
} int K;
int f[sz];
int id[sz],fa[sz],cnt;
#define v edge[i].t
void dfs(int x,int fa)
{
::fa[x]=fa;
go(x) if (v!=fa) dfs(v,x);
id[++cnt]=x;
}
int check(int len)
{
K=len;
int ret=0;
rep(i,1,n)
{
int x=id[i],mx1=0,mx2=0;
go(x) if (v!=fa[x])
{
if (f[v]>mx1) mx2=mx1,mx1=f[v];
else if (f[v]>mx2) mx2=f[v];
}
if (mx1+mx2+1>=K) ++ret,f[x]=0;
else f[x]=mx1+1;
}
return ret;
}
#undef v int ans[sz]; void solve(int l,int r,int L,int R)
{
if (r<l) return;
if (L==R) { rep(i,l,r) ans[i]=L; return; }
int mid=(l+r)>>1,s=check(mid);
ans[mid]=s;
solve(l,mid-1,s,R),solve(mid+1,r,L,s);
} int main()
{
file();
read(n);
int x,y;
rep(i,1,n-1) read(x,y),make_edge(x,y);
dfs(1,0);
/*
int T=sqrt(n*log2(n));
rep(i,1,T) ans[i]=check(i);
int las=T;
drep(i,n/T,0)
{
int l=las+1,r=n,R=-1;
while (l<=r)
{
int mid=(l+r)>>1;
if (check(mid)>=i) R=mid,l=mid+1;
else r=mid-1;
}
rep(j,las+1,R) ans[j]=i;
las=max(las,R);
}
rep(i,1,n) printf("%d\n",ans[i]);
*/
solve(1,n,0,n);
rep(i,1,n) printf("%d\n",ans[i]);
return 0;
}

Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]的更多相关文章

  1. CF1039D You Are Given a Tree 根号分治、二分、贪心

    传送门 似乎直接做不太好做-- 当你不会做的时候就可以考虑根号算法了(或许是这样的 考虑如果只有一个询问如何计算答案. 显然是可以贪心的,思路与NOIP2018D1T3是相同的.每一个点向上传一条链, ...

  2. 【bzoj2506】calc 根号分治+STL-vector+二分+莫队算法

    题目描述 给一个长度为n的非负整数序列A1,A2,…,An.现有m个询问,每次询问给出l,r,p,k,问满足l<=i<=r且Ai mod p = k的值i的个数. 输入 第一行两个正整数n ...

  3. CF1039D You Are Given a Tree 根号分治,贪心

    CF1039D You Are Given a Tree LG传送门 根号分治好题. 这题可以整体二分,但我太菜了,不会. 根号分治怎么考虑呢?先想想\(n^2\)暴力吧.对于每一个要求的\(k\), ...

  4. codeforces 1065F Up and Down the Tree

    题目链接:codeforces 1065F Up and Down the Tree 题意:给出一棵树的节点数\(n\)以及一次移动的最大距离\(k\),现在有一个标记在根节点1处,每一次可以进行一下 ...

  5. Codeforces 914H Ember and Storm's Tree Game 【DP】*

    Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...

  6. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  7. CF804D Expected diameter of a tree 树的直径 根号分治

    LINK:Expected diameter of a tree 1e5 带根号log 竟然能跑过! 容易想到每次连接两个联通快 快速求出直径 其实是 \(max(D1,D2,f_x+f_y+1)\) ...

  8. [CF1039D]You Are Given a Tree[贪心+根号分治]

    题意 给你\(n\)个点的树,其中一个简单路径的集合被称为\(k\)合法当且仅当树的每个节点最多属于一条路径,且每条路径包含\(k\)个节点.对于每个\(k(k \in [1,n])\),输出最多的\ ...

  9. CF1039D-You Are Given a Tree【根号分治,贪心】

    正题 题目链接:https://www.luogu.com.cn/problem/CF1039D 题目大意 给出\(n\)个点的一棵树,然后对于\(k\in[1,n]\)求每次使用一条长度为\(k\) ...

随机推荐

  1. C++ 出现异常“.... \debug_heap.cpp Line:980 Expression:__acrt_first_block==header"

    本人是在写dll项目中出现了这个问题,经过一天的研究,尝试了三个步骤1.在配置属性->常规->MFC的使用中,将在静态库中使用MFC改为在共享DLL中使用MFC.但是还会出错2.原因是dl ...

  2. python随机数random模块

    需要  import random x=random.random()    产生 0 到 1 之间的随机浮点数 结果  0.005570080000840916 x=random.randint(1 ...

  3. matplotlib-2D绘图库-面向对象

    个人理解:plt--画本    figure--产生画纸 子图 import numpy as np import matplotlib.pyplot as plt #解决能显示中文 plt.rcPa ...

  4. spring cloud心跳检测自我保护(EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.)

    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER ...

  5. python基础(八种数据类型)

    Python的八种数据类型 八种数据类型分别是: number(数字).string(字符串).Boolean(布尔值).None(空值) list(列表).tuple(元组).dict(字典).se ...

  6. day 7 - 1 集合、copy及基础数据类型汇总

    集合:{},可变的数据类型,他里面的元素必须是不可变的数据类型,无序,不重复.(不重要)集合的书写 set1 = set({1,2,3}) #set2 = {1,2,3,[2,3],{'name':' ...

  7. linux(ubuntu) python 版本切换

    参考链接:https://blog.csdn.net/thankyou0/article/details/79610854

  8. python 三大框架之一Flask入门

    Flask轻量级框架,Flask是python中的轻量级框架. 打开终端 输入pip install Flask 命令 下载以及安装Flask框架 检查是否下载成功及能否使用 首先导入python环境 ...

  9. vim设置行号

    vim打开文件后在底行模式下输入:set nu可以在文件每行开头显示对应的行数: 若想vim打开文件默认显示行数,执行:vim /etc/vimrc,在打开的文件末尾添上:set nu,保存退出即可!

  10. python 携带cookie获取页面内容

    有时会遇到爬取的页面需要登录,这就要带上cookie了. 下面记录了几种携带cookie的方法 # coding=utf-8 import requests s = requests.Session( ...