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 < ...
随机推荐
- pg_resetxlog - 重置一个 PostgreSQL 数据库集群的预写日志以及其它控制内容
SYNOPSIS pg_resetxlog [ -f ] [ -n ] [ -o oid] [ -x xid] [ -l fileid,seg] datadir DESCRIPTION 描述 pg_r ...
- [POI2007]POW-The Flood(并查集)
[POI2007]POW-The Flood Description AKD 市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD 市全被水淹没了.Blue Mary,AKD 市的市长,召集了 ...
- 2018-08-01-weekly
Algorithm 4. Median of Two Sorted Arrays What 两个排序数组的中位数 How 两个数组合并到同一个数组,然后进行排序取中间值即可 Key Codes cla ...
- 【转载】Mysql注入点在limit关键字后面的利用方法
描写sql注入利用方法的文章数不胜数,本文将描述一种比较特殊的场景. 细节 在一次测试中,我碰到了一个sql注入的问题,在网上没有搜到解决办法,当时的注入点是在limit关键字后面,数据库是MyS ...
- python tkinter实时显示曲线
from tkinter import *from tkinter import ttkimport time#画窗口root = Tk()root.geometry('1000x500')root. ...
- navicat的使用(测试库和正式库同步)以及用plsql改表字段属性
说明:数据库的操作,除了查询,最好先做好备份,比如数据同步.更新.修改或删除之类的: netstat -antp 查看mysql端口 firewall -cmd --list-all 查看防 ...
- Selenium-Switch与SelectApi介绍
Switch 我们在UI自动化测试时,总会出现新建一个tab页面,弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...
- sql2000如何完美压缩.mdf文件
--收缩数据库 dbcc shrinkdatabase('test_db') , ) --数据文件mdf , ) --日志文件ldf ) --更新
- ps磨皮的方法
磨皮顾名思义就是将皮肤模糊掉,它可以去除皮肤上的一些斑点以及细纹,从而使皮肤看起来更加光滑.下面就是两张磨皮前后的对比图,很明显右边的人物的皮肤看起来要更好一些:给人的视觉效果也更年轻一点. 磨皮前后 ...
- 基于MyBatis实现Dao编程
基于MyBatis实现Dao编程 1.建立mybatis-config.xml文件 <?xml version="1.0" encoding="UTF-8" ...