BZOJ 4675(点分治)
题面
分析
由于期望的线性性,我们可以分别计算每个点对对答案的贡献
有三个人取数字,分开对每个人考虑
设每个人分别取了k个数,则一共有\(C_n^k\)种组合,选到每种组合的概率为\(\frac{1}{C_n^k}\)
对于一个幸运点对,包含它的组合有\(C_{n-2}^{k-2}\)种(k个点中有2个点是该点对,再从剩下的n-2个点中选k-2个点,每种的贡献均为1)
所以每一个点对的贡献是
\]
因此总答案为\(a \times \frac{k(k-1)}{n(n-1)}\),其中a为幸运点对的数量
所以只要求出幸运点对数量即可
对于每一个幸运数num[i],我们进行一次点分治,求出长度为num[i]的路径数(直接套点分治板子,先求长度>=num[i]的路径数,再减去长度>num[i]的路径数量),并累计进答案
注意最后n*(n-1)要用double,否则会爆int
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50005
using namespace std;
int n,k;
struct edge{
int from;
int to;
int next;
}E[maxn<<1];
int ecnt=1;
int head[maxn];
inline void add_edge(int u,int v){
ecnt++;
E[ecnt].from=u;
E[ecnt].to=v;
E[ecnt].next=head[u];
head[u]=ecnt;
}
int root=0,sum;
int f[maxn];
int sz[maxn];
int vis[maxn];
void get_root(int x,int fa){
sz[x]=1;
f[x]=0;
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa&&!vis[y]){
get_root(y,x);
sz[x]+=sz[y];
f[x]=max(f[x],sz[y]);
}
}
f[x]=max(f[x],sum-f[x]);
if(f[x]<f[root]) root=x;
}
int cnt=0;
int deep[maxn];
int res[maxn];
void get_deep(int x,int fa){
res[++cnt]=deep[x];
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa&&!vis[y]){
deep[y]=deep[x]+1;
get_deep(y,x);
}
}
}
int calc(int x,int d0){
deep[x]=d0;
cnt=0;
get_deep(x,0);
sort(res+1,res+1+cnt);
int l=1,r=cnt;
int ans1=0;
while(l<r){
if(res[l]+res[r]<=k){
ans1+=(r-l);
l++;
}else r--;
}
l=1,r=cnt;
int ans2=0;
while(l<r){
if(res[l]+res[r]<k){
ans2+=(r-l);
l++;
}else r--;
}
return ans1-ans2;
}
int ans=0;
void solve(int x){
vis[x]=1;
ans+=calc(x,0);
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(!vis[y]){
ans-=calc(y,1);
root=0;
sum=sz[y];
get_root(y,0);
solve(root);
}
}
}
void divide_ini(){
memset(deep,0,sizeof(deep));
memset(f,0,sizeof(f));
memset(sz,0,sizeof(sz));
memset(vis,0,sizeof(vis));
root=0;
sum=n;
f[0]=n;
get_root(1,0);
}
int m;
int num[maxn];
int main(){
int u,v;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d",&num[i]);
}
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=m;i++){
k=num[i];
divide_ini();
solve(root);
}
double k1,k2,k3;
if(n%3==0) k1=k2=k3=n/3;
else if(n%3==1){
k1=n/3+1;
k2=n/3;
k3=n/3;
}else{
k1=n/3+1;
k2=n/3+1;
k3=n/3;
}
printf("%.2lf\n",ans*k1*(k1-1)/((double)n*(n-1)));//强制转成double,防止溢出
printf("%.2lf\n",ans*k2*(k2-1)/((double)n*(n-1)));
printf("%.2lf\n",ans*k3*(k3-1)/((double)n*(n-1)));
}
BZOJ 4675(点分治)的更多相关文章
- bzoj 4025 二分图 分治+并查集/LCT
bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...
- BZOJ 1468 & 点分治
题意: 带权树,求距离小于k的点对数目. SOL: 参考http://blog.csdn.net/jiangshibiao/article/details/25738041解决了题意问题... 代码是 ...
- 【BZOJ 4059】 (分治暴力|扫描线+线段树)
4059: [Cerc2012]Non-boring sequences Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 632 Solved: 22 ...
- bzoj 1176 CDQ分治
思路:首先我们将问题转换一下,变成问在某个点左下角的权值和,那么每一个询问可以拆成4的这样的询问,然后 进行CDQ 分治,回溯的时候按x轴排序,然后用树状数组维护y的值. #include<bi ...
- bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...
- bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 首先考虑DP做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...
- bzoj 2599(点分治)
2599: [IOI2011]Race Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 3642 Solved: 1081[Submit][Statu ...
- BZOJ 1537 cdq分治
思路: 我只是想写一下cdq-- 二维偏序 一维排序 一维cdq分治 (我忘了归并排序怎么写了,,,) 写了个sort- 复杂度是O(nlog^2n) //By SiriusRen #include ...
- BZOJ 3262 cdq分治 OR 树套树
注意判断 三个条件都一样的-- (CDQ分治 其实并不是很难理解 只是想不到--) CDQ分治: //By SiriusRen #include <cstdio> #include < ...
随机推荐
- ASE Backend Alpha Sprint Review
[Backend] Alpha Review展示博客 团队成员介绍:仅限于Alpha阶段有贡献的成员. 典型场景描述:描述并说明你们认为的产品面向的典型场景. 团队管理与协作:包括但不限于团队内部如何 ...
- 1、获取ip地址
1.获取ip地址 System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() .Select(p => p. ...
- Linux架构之Nginx 负载均衡会话保持
案例No.50:Nginx负载均衡会话保持 前期准备环境 web01.web02 (web01.web02.db01.nfs01都要优化基本源)[root@web01 ~]# vim /etc/yum ...
- java并发学习--第三章 线程安全问题
线程的安全问题一直是我们在开发过程中重要关注的地方,出现线程安全问题的必须满足两个条件:存在着两个或者两个以上的线程:多个线程共享着共同的一个资源, 而且操作资源的代码有多句.接下来我们来根据JDK自 ...
- bzoj2402 陶陶的难题II 分数规划+树剖+线段树维护凸壳+二分
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2402 题解 看上去很像分数规划的模型.于是就二分吧.令 \[ \begin{align*}\f ...
- How to permanently set $PATH on Linux/Unix?
You need to add it to your ~/.profile or ~/.bashrc file. export PATH=$PATH:/path/to/dir Depending on ...
- 对provide/inject的研究
1.组件中通过provider来提供变量,然后在子组件中通过inject来注入变量. 2.在父组件中定义: provide () { return { secondPageTableRoot: { t ...
- linux运维、架构之路-HTTP服务
一.HTTP协议 1.介绍 HTTP协议,全称HyperText Transfer Protocol,中文名为超文本传输协议,是互联网中最常用的一种网络协议.HTTP协议是互联网上常用的通信协议之一. ...
- spring boot构建
1.新建Maven工程 1.File-->new-->project-->maven project 2.webapp 3.工程名称 k3 2.Maven 三个常用命令 选 项目右击 ...
- 【HDOJ6686】Rikka with Travels(树形DP)
题意:给定一棵n个点,边权为1的树,求有多少个有序数对(l1,l2)使得存在两条互不相交的路径,长度分别为l1和l2 n<=1e5 思路: #include<bits/stdc++.h&g ...