Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]
根号分治真是妙啊。
思路
考虑对于单独的一个\(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 [根号分治,整体二分,贪心]的更多相关文章
- CF1039D You Are Given a Tree 根号分治、二分、贪心
传送门 似乎直接做不太好做-- 当你不会做的时候就可以考虑根号算法了(或许是这样的 考虑如果只有一个询问如何计算答案. 显然是可以贪心的,思路与NOIP2018D1T3是相同的.每一个点向上传一条链, ...
- 【bzoj2506】calc 根号分治+STL-vector+二分+莫队算法
题目描述 给一个长度为n的非负整数序列A1,A2,…,An.现有m个询问,每次询问给出l,r,p,k,问满足l<=i<=r且Ai mod p = k的值i的个数. 输入 第一行两个正整数n ...
- CF1039D You Are Given a Tree 根号分治,贪心
CF1039D You Are Given a Tree LG传送门 根号分治好题. 这题可以整体二分,但我太菜了,不会. 根号分治怎么考虑呢?先想想\(n^2\)暴力吧.对于每一个要求的\(k\), ...
- codeforces 1065F Up and Down the Tree
题目链接:codeforces 1065F Up and Down the Tree 题意:给出一棵树的节点数\(n\)以及一次移动的最大距离\(k\),现在有一个标记在根节点1处,每一次可以进行一下 ...
- Codeforces 914H Ember and Storm's Tree Game 【DP】*
Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...
- Codeforces Round #499 (Div. 1) F. Tree
Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...
- CF804D Expected diameter of a tree 树的直径 根号分治
LINK:Expected diameter of a tree 1e5 带根号log 竟然能跑过! 容易想到每次连接两个联通快 快速求出直径 其实是 \(max(D1,D2,f_x+f_y+1)\) ...
- [CF1039D]You Are Given a Tree[贪心+根号分治]
题意 给你\(n\)个点的树,其中一个简单路径的集合被称为\(k\)合法当且仅当树的每个节点最多属于一条路径,且每条路径包含\(k\)个节点.对于每个\(k(k \in [1,n])\),输出最多的\ ...
- CF1039D-You Are Given a Tree【根号分治,贪心】
正题 题目链接:https://www.luogu.com.cn/problem/CF1039D 题目大意 给出\(n\)个点的一棵树,然后对于\(k\in[1,n]\)求每次使用一条长度为\(k\) ...
随机推荐
- C# UpdatePanel加载完毕回调JS
如果 我们想UpdatePanel加载完成后做一些事情 需要使用js <script type="text/javascript"> //给ScriptManager的 ...
- java mongoTemplate的group统计
@Service public class MongoCountServiceImpl implements MongoCountService { @Autowired private MongoT ...
- excel数据 入库mysql 和 mysql数据 导入excel文件
1.excel数据入库mysql 首先准备excel文件, 标红的地方需要留意,一个是字段名所在行,一个表名对应页: 然后私用mysql工具 navicat, 选择数据库,然后导入文件, 选中相应ex ...
- Kali Linux之web安全扫描器skipfish使用
0x00.skipfish简介 谷歌公司出品的开源web程序评估软件. skipfish特点:CPU资源占用低,扫描速度快,每秒可以轻松处理2000个请求,误报率低. 1x00.skipfish使用 ...
- border-radius图解
自己看了理解的border-radius: 设置参数: 100*100的正方形,第一个:border-top-left-radius:100px 100px,即圆的半径为100px.圆弧与上和左bor ...
- BootStrap表单验证用户名重复
html: <div class="form-group"> <label for="username" class="contro ...
- 微信支付-H5网页支付开通流程
简介 H5 支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付.主要用于触屏版的手机浏览器请求微信支付的场景.可以方便的从外 ...
- 【转载】双调排序Bitonic Sort,适合并行计算的排序算法
双调排序是data-independent的排序, 即比较顺序与数据无关的排序方法, 特别适合做并行计算,例如用GPU.fpga来计算. 1.双调序列 在了解双调排序算法之前,我们先来看看什么是双调序 ...
- 论文笔记系列-Neural Network Search :A Survey
论文笔记系列-Neural Network Search :A Survey 论文 笔记 NAS automl survey review reinforcement learning Bayesia ...
- python,魔法方法指南
1.简介 本指南归纳于我的几个月的博客,主题是 魔法方法 . 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加“魔法”的特殊方法. 它们经常是两个下划线包围来命名的 ...