bzoj 3528: [Zjoi2014]星系调查
Description
银河历59451年,在银河系有许许多多已被人类殖民的星系。如果想要在行
Input
第一行是N,M,分别表示这个银河系内的行星系的个数
Output
总共Q行,每一行一个实数,表示花花第i次需要计算的答
Sample Input
6 6
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;
}
转载于:https://www.cnblogs.com/qt666/p/6798486.html
bzoj 3528: [Zjoi2014]星系调查相关推荐
- [ZJOI2014] 星系调查(树上差分 + 数学推式子)
problem luogu-P3340 题面写得那么长,其实说白了就是求一条直线,使得若干个点到这条直线的距离平方的和最小,求这个最小值. solution 我超爱数学,数学就是我的命,我一天不学数学 ...
- BZOJ.3527.[ZJOI2014]力(FFT)
题目链接 \(Descripiton\) 给出\(q[\ ]\),\[F[j]=\sum_{i<j}\frac{q_iq_j}{(i-j)^2}-\sum_{i>j}\frac{q_iq_ ...
- BZOJ 3527: [ZJOI2014]力(FFT)
题意 给出\(n\)个数\(q_i\),给出\(Fj\)的定义如下: \[F_j=\sum \limits _ {i < j} \frac{q_iq_j}{(i-j)^2}-\sum \limi ...
- BZOJ 2768 [JLOI2010]冠军调查
还说还剩十分钟A一道水题,然后发现和善意的投票一模一样粘个代码过去直接A... 装作自己又写了一道题. 题面 //Twenty #include<cstdio> #include<c ...
- 数学(FFT):BZOJ 3527 [Zjoi2014]力
题目在这里:http://wenku.baidu.com/link?url=X4j8NM14MMYo8Q7uPE7-7GjO2_TXnMFA2azEbBh4pDf7HCENM3-hPEl4mzoe2w ...
- ZJOI 2014 星系调查(推导)
题意 https://loj.ac/problem/2201 思路 说白了就是一条路径上有 \(n\) 个二维坐标,求一条直线使得所有点到此直线的距离和最小. 设这条直线为 \(y=kx+b\) ,距 ...
- bzoj 3519: [Zjoi2014] 消棋子 题解
[序言]在大家怀疑的眼光下,我做了一个中午和半个下午.调了一个晚上的题目总算A了! [原题] 消棋子是一个有趣的游戏.游戏在一个r * c的棋盘上进行.棋盘的每一个格 子.要么是空,要么是一种颜色的棋 ...
- bzoj 3527 [Zjoi2014]力——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3527 把 q[ i ] 除掉.设 g[ i ] = i^2 ,有一半的式子就变成卷积了:另一 ...
- BZOJ 3527: [Zjoi2014]力
题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3527 题目大意:见原题. 算法讨论: 设A[i]=q[i],B[i]=1/(i^2). 设 ...
最新文章
- leetcode题解【持续更新】
- MongoDB基本命令总结
- 2017CCPC 杭州 J. Master of GCD【差分标记/线段树/GCD】
- psv黑商店pkgj最新版下载_e收银app下载安装_e收银软件最新版免费下载
- 但我发现了幸福的超级玛丽
- 2、Python函数详解(0601)
- java 反射父类私有属性值_如何在Java中通过反射访问父类的父类的私有字段? - java...
- Java从入门到精通 第21章 Annotation
- Java的System.out.println并不等于C的printf
- cwm oracle,ORA-06512: at OLAPSYS.CWM2_OLAP_UTILITY
- HTTP 状态码大全
- 自己推荐的经典好书展示(计算机、企业管理学、生存)
- NLTK文本分割器是如何工作的
- Arduino接入DFrobot EasyIOT实验(Arduino+APP Inventor+EasyIOT+百度AI API+Python数据可视化)
- Java Socket 如何接收byte和String
- SpringBoot整合redis使用setnx完成分布式锁
- JS实现在线汉字笔画练习特效(平板移动端可用)
- 【React Native】集成声网Agora语音通讯
- 3.每天一个java小程序之累加累乘
- 操作系统与网络实现 之十八(丁)