洛谷

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. ssh免密登录及去掉提示

    A连B 1.生成公钥和私钥    ssh-keygen2.复制公钥到需要免密登录的服务器上  ssh-copy-id root@192.168.25.175 A连A 2.复制公钥到本机上  ssh-c ...

  3. Oracle数据库XXE注入漏洞(CVE-2014-6577)分析

    在这篇文中,我们将共同分析一下Oracle数据库的XXE注入漏洞(CVE-2014-6577),Oracle公司1月20日发布了针对该漏洞的相关补丁. 有关XXE的相关知识,可以查看安全脉搏站内的另一 ...

  4. tensorflow 学习

    tensorflow: tensor 沿着graph 传递闭包完成flow的过程. 简单运算: import tensorflow as tf # Build a graph. a = tf.cons ...

  5. vue安装教程总结

    转载:https://blog.csdn.net/sunny1660/article/details/78326548 简介:       vue.js是一套构建用户界面的渐进式框架.比较简洁,用于解 ...

  6. 一个简单至极的PHP缓存类代码

    https://www.jb51.net/article/73836.htm 直接看代码吧!使用说明:1.实例化$cache = new Cache(); 2.设置缓存时间和缓存目录$cache = ...

  7. CCSprite使用记录

    CCSprite使用需要CCTexture2D,就是需要纹理.可以设置绘制纹理的区域. CCSprite 有 draw方法 ,由CCDirector/mainLoop()调用(当前使用的场景为根,向下 ...

  8. 洛谷P1494 【[国家集训队]小Z的袜子】

    纪念自己独立完成的一道省选题(菜鸡如我只会看题解qwq) 还算是一道比较裸的莫队题把,比有的题目简单很多,也很好想怎么O(1)转移,比别的题就多了一个组合数计算(还有gcd??),还没算%意义下,也是 ...

  9. sublime text 3 左侧目录树中文文件夹显示方框问题解决

    0 - 解决方法 打开Preferences->Settings 在弹出的Settings对话框中,加入"dpi_scale": 1.0 重新启动sublime text 3 ...

  10. vmware常用命令

    控制台桌面执行快捷键ctrl+alt+f2 可以进入命令行