bzoj 3528: [Zjoi2014]星系调查
Description
银河历59451年,在银河系有许许多多已被人类殖民的星系。如果想要在行
Input
第一行是N,M,分别表示这个银河系内的行星系的个数
Output
总共Q行,每一行一个实数,表示花花第i次需要计算的答
Sample Input
3 4
5 6
1 3
4 4
3 3
2 4
1 2
1 3
2 3
2 4
3 5
5 6
3
3 6
2 4
4 6
Sample Output
0.66667
0.00000
1.67544
一道良心的必修一压轴题+树链剖分
通过一系列漫长的推导+勇敢的展开,最后只需要维护
推导的话主要是运用两次主元法(点到直线距离公式要记得),最后由求根公式即可,推导以后补:
设最后的那条直线的解析式为y=kx+b,设n为路径上的点数
由点到直线的距离公式:
带入暴算并把b当做主元:
分子是一个二次函数形式,可以计算出整个式子取最小值时的b值(二次函数顶点)
令:
则 b=yar-xar;
在把b带入以k为主元:
可以把分子变为一个关于k的二次函数形式:
令:
则 暴力计算可得到
所以
乘过去:
由于有解,所以
所以:
易知在Ans取较小的那个零点的时候为所求答案,由求根公式计算即可;
不容易啊
因为图连通且不超过n条边,所以为树或者一个基环树
树的话直接树链剖分,维护的东西直接用树上前缀和即可: x+y-lca-fa[lca];
基环树的话,把环看做根节点后就是树了,如果lca为环的话分别跳到环上,
环上的按照某种时针顺序预处理前缀和,然后分别走两条路统计即可.
如果lca不是环就正常树的即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define RG register
using namespace std;
const int N=300050;
int n,m,cnt,tot,root[N],head[N],to[N],nxt[N],fa[N],dep[N],size[N],son[N],top[N],cir[N],rt[N];
int tx[N],ty[N],vis[N];
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
struct data{
int pre[6];
void update(RG int u,RG int v){
pre[0]++;pre[1]+=u;pre[2]+=u*u;
pre[3]+=v;pre[4]+=v*v;pre[5]+=u*v;
}
double query(){
RG double n=pre[0],totx=pre[1],toty=pre[3],totx2=pre[2],toty2=pre[4],totxy=pre[5];
RG double xar=totx/n,yar=toty/n;
RG double a=totx2-2*xar*totx+n*xar*xar;
RG double b=2*yar*totx+2*xar*toty-2*totxy-2*n*xar*yar;
RG double c=toty2-2*yar*toty+n*yar*yar;
RG double A=4.0,B=-4*(a+c),C=4*a*c-b*b;
return (-B-sqrt(B*B-4*A*C))/2/A;
}
}a[N],b[N];
data operator +(data x,data y){
for(RG int i=0;i<6;i++) x.pre[i]+=y.pre[i]; return x;
}
data operator -(data x,data y){
for(RG int i=0;i<6;i++) x.pre[i]-=y.pre[i]; return x;
}
void lnk(RG int x,RG int y){
to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}
inline void dfs1(int x,int f){
vis[x]=1;size[x]=1;son[x]=0;rt[x]=f;
a[x]=a[fa[x]]; a[x].update(tx[x],ty[x]);
for(RG int i=head[x];i;i=nxt[i]){
RG int y=to[i];
if (!vis[y]&&y!=fa[x]){
dep[y]=dep[x]+1;fa[y]=x;
dfs1(y,f);size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
}
inline void dfs2(RG int x,RG int f){
top[x]=f;
if(son[x]) dfs2(son[x],f);
for (RG int i=head[x]; i; i=nxt[i]){
RG int y=to[i];
if(x==fa[y] && y!=son[x]) dfs2(y,y);
}
}
inline int lca(RG int x,RG int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
return y;
}
inline void work(){
memset(vis,0,sizeof(vis));
for(RG int x=1;x<=n;x++)
for(RG int i=head[x];i;i=nxt[i]){
if(fa[x]!=to[i]&&fa[to[i]]!=x){
RG int y=to[i];
if(dep[x]>dep[y]) swap(x,y);
for(;y!=x;y=fa[y]){
root[++cnt]=y;cir[y]=cnt;vis[y]=1;
b[cnt]=b[cnt-1];b[cnt].update(tx[y],ty[y]);
}
root[++cnt]=x;cir[x]=cnt;vis[x]=1;
b[cnt]=b[cnt-1];b[cnt].update(tx[x],ty[x]);
return;
}
}
}
int main(){
n=gi(),m=gi();RG int x,y;
for(RG int i=1;i<=n;i++) tx[i]=gi(),ty[i]=gi();
for(RG int i=1;i<=m;i++){
x=gi(),y=gi();
lnk(x,y); lnk(y,x);
}
dfs1(1,1);
memset(vis,0,sizeof(vis));
if(n==m) work();else root[cnt=1]=1;
memset(fa,0,sizeof(fa));
for(RG int i=1;i<=cnt;i++){
dfs1(root[i],root[i]); dfs2(root[i],root[i]);
}
RG int Q=gi();data u,v;
for(RG int i=1;i<=Q;i++){
x=gi(),y=gi();
if (rt[x]==rt[y]){
u=a[x]+a[y]-a[lca(x,y)]-a[fa[lca(x,y)]];
printf("%.5f\n",u.query());
} else{
if (cir[rt[x]]>cir[rt[y]]) swap(x,y);
u=a[x]-a[rt[x]]+a[y]-a[rt[y]]+b[cir[rt[y]]]-b[cir[rt[x]]-1];
v=a[x]-a[rt[x]]+a[y]-a[rt[y]]+b[cir[rt[x]]]+b[cnt]-b[cir[rt[y]]-1];
printf("%.5f\n",min(u.query(),v.query()));
}
}
return 0;
}
bzoj 3528: [Zjoi2014]星系调查的更多相关文章
- bzoj 3528 [ZJOI2014] 星系调查 题解
[原题] 星系调查 [问题描写叙述] 银河历59451年.在银河系有许很多多已被人类殖民的星系.如果想要在行 星系间往来,大家一般使用连接两个行星系的跳跃星门. 一个跳跃星门能够把 物质在它所连接的 ...
- bzoj 3528 [Zjoi2014]星系调查【树链剖分+数学】
参考:https://www.cnblogs.com/zhuohan123/p/3698852.html 首先,根据点到直线距离公式 \[ d=\frac{kx_0-y_0+b}{\sqrt{k^{2 ...
- BZOJ3528: [Zjoi2014]星系调查
唉,看到这题直接想起自己的Day1,还是挺难受的,挺傻一题考试的时候怎么就没弄出来呢…… 这两天CP让我给他写个题解,弄了不是很久就把这个题给弄出来了,真不知道考试的时候在干嘛. 明天就出发去北京了, ...
- 题解 洛谷 P3340 【[ZJOI2014]星系调查】
根据题意,发现题目中的图,其实就是一颗树或者是一颗基环树,每个节点上有一个点对\((x,y)\),每次询问为给定端点,找一条直线到端点间的所有点的距离之和最小. 设这条直线为\(y=kx+b\),根据 ...
- 「ZJOI2014」星系调查
「ZJOI2014」星系调查 本题核心在于快速求XPs 的线性假设相斥度. 点\((x1,y1)\)到直线\(y=kx+b\)的距离的平方为\(\displaystyle {(kx1+b-y1)^2} ...
- BZOJ 2768: [JLOI2010]冠军调查 最小割
2768: [JLOI2010]冠军调查 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2768 Description 一年一度的欧洲足 ...
- 【bzoj 3786】星系探索
Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球 ...
- BZOJ 3527: [Zjoi2014]力
Description 求 \(E_i=\sum _{j=0}^{i-1} \frac {q_j} {(i-j)^2}-\sum _{j=i+1}^{n-1} \frac{q_j} {(i-j)^2} ...
- bzoj 2768: [JLOI2010]冠军调查
#include<cstdio> #include<iostream> #define M 100000 #include<cstring> using names ...
随机推荐
- RecyclerView分割线——万能分割线
参照网络上众多的分割线设计方法,对方法进行调整和修改,最终完成的比较通用的RecyclerView分割线,底部会附上参考网址,大家可以去看一下. 在正文之前,先说一下个人看法:研究下来,我发现,其实最 ...
- Android 在通知栏实现计时功能
Notification是APP 向系统发出通知时,它将先以图标的形式显示在通知栏中.用户可以下拉通知栏查看通知的详细信息.我们可以在通知栏实现自定义的效果,也可以结合service和BroadCas ...
- Python函数篇
1.函数名的命名规则: 函数名必须以下划线或字母开头,可以包含任意字母.数字或下划线的组合.不能使用任何的标点符号: 函数名是区分大小写的. 函数名不能是保留字. 2. 形参和实参 形参:形式参数,不 ...
- 集合、增强for、泛型
Collection集合:Collection是层次结构中的根接口,存储的元素为对象,(也就是说只能存储引用数据类型,不能存储基础数据类型),具体可查询API.集合与数组的区别:1.集合只能存放引用数 ...
- 【转】千万不要在JS中使用连等赋值操作
原文链接 千万不要在JS中使用连等赋值操作 目录 前言 赋值顺序? 连续赋值能拆开写么? 后记 前言 文章标题这句话原本是在国外某JavaScript规范里看到的,当时并没有引起足够的重视,直到最 ...
- 使用JSCH框架通过跳转机访问其他节点
之前搞了套远程访问ssh进行操作的代码,最近有需求,需要通过一台跳转机才能访问目标服务.在网上搜了半天,也没找到比较好的例子,就自己翻阅了下JSCH的API.但是看的云里雾里的.联想了下,端口转发的原 ...
- 【LintCode·入门】斐波那契数列
斐波那契数列 描述 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...
- Android Weekly Notes Issue #286
December 3rd, 2017 Android Weekly Issue #286 本期文章包含如何通过踩坑来学习Kotlin,以及利用Kotlin的data class做MVVM状态保存,还包 ...
- 真正的精通Java是种什么样的境界?
会在不适合使用java的地方不用java! 作为一名软件开发者,要追求的,应该是不断地提升自己分析问题把握事物关键点,实事求是地给出切实可行且能"一剑封喉"的优雅解决方案的能力,再 ...
- DirectX:在graph自己主动连线中增加自己定义filter(graph中遍历filter)
为客户提供的视频播放的filter的測试程序中,採用正向手动连接的方式(http://blog.csdn.net/mao0514/article/details/40535791).因为不同的视频压缩 ...