[cf566C]Logistical Questions
记$d(x,y)$为$x$到$y$的距离,$cost_{x}=\sum_{i=1}^{n}w_{i}d(x,i)^{\frac{3}{2}}$为$x$的代价
取$C$为足够大量,对于一条边权为$w$的边,在边上新建$wC-1$个点,这些点点权为0(即本身无影响),并将边拆成$wC$段,那么每一段边权为$\frac{1}{C}$
任取(新树中)一条路径$\{a_{1},a_{2},...,a_{l}\}$,则$cost_{a_{i}}$具有凸性
根据凸性定义,即求证$\forall 2\le j\le l-1,2cost_{a_{j}}\le cost_{a_{j-1}}+cost_{a_{j+1}}$
代入其式子,不妨对每一个$i$都保证此性质,也即求证$2d(a_{j},i)^{\frac{3}{2}}\le d(a_{j-1},i)^{\frac{3}{2}}+d(a_{j+1},i)^{\frac{3}{2}}$
对$i$的位置分类讨论:
1.$i$距离$a_{j}$最近,则$d(a_{j},i)\le d(a_{j-1},i),d(a_{j+1},i)$,显然成立
2.$i$不距离$a_{j}$最近,记$x=d(a_{j},i)$,那么即$2x^{\frac{3}{2}}\le (x-\frac{1}{C})^{\frac{3}{2}}+(x+\frac{1}{C})^{\frac{3}{2}}$
令$f(x)=x^{\frac{3}{2}}$,代入并移项,也即$f(x)-f(x-\frac{1}{C})\le f(x+\frac{1}{C})-f(x)$
当$C$足够大时,两者可以看作$\frac{f'(x)}{C}$和$\frac{f'(x+\frac{1}{C})}{C}$,注意到$f'(x)=\frac{3}{2}x^{\frac{1}{2}}$单调递增,即成立
进而考虑其中非新建的点$\{b_{1},b_{2},...,b_{k}\}$,根据$cost_{a_{i}}$的凸性,$cost_{b_{i}}$的形式必然是先严格单调递减、再有若干个相同的数(最小值)、最后严格单调递增(首尾两段允许为空)
由于(原树中)任意一条路径都可以被以此法选择,即所有路径都为此形式
(以下删去上述新建的点,即仍考虑原树)
约定$x$为质心当且仅当$\forall 1\le i\le n,cost_{x}\le cost_{i}$,题目即要找到任意一个质心即可
任取一点$x$,对与$x$相邻的点$y$,至多存在一个$y$满足$cost_{y}<cost_{x}$
(否则任取其中两个记为$y_{1}$和$y_{2}$,考虑$y_{1}$到$y_{2}$的路径即矛盾)
进一步的,再对其分类讨论:
1.如果不存在$y$满足$cost_{y}<cost_{x}$,则对于树上任意一点$z$,考虑其到$x$的路径,由于最后一步仍没有递增,根据路径的形式不难得到$cost_{x}\le cost_{z}$,也即$x$为质心
2.如果存在$y$满足$cost_{y}<cost_{x}$,那么对于以$y$为根时$x$子树中的任意一点$z$,考虑其到$y$的路径,由于最后一步严格单调递减,根据路径的形式不难得到$cost_{y}<cost_{z}$,也即$z$一定不为质心
综上,不难得到下述暴力做法——
初始连通子树$T_{0}=T$,并任取$T_{0}$中一点$x$,求出所有与$x$相邻的点$y$的答案,若不存在$y$满足$cost_{y}<cost_{x}$则$x$为质心,若存在$y$满足$cost_{y}<cost_{x}$(必然唯一)令$T_{0}$为删去$x$后$y$所在的连通块并递归即可(第二种情况,剩下的部分一定不包含质心)
如果令$x$为$T_{0}$中的重心(指通常的定义),那么每一次$T_{0}$的规模至少缩小一半,即至多$o(\log n)$层
但如果暴力计算所有$y$,仍会导致复杂度过高(每一次计算是$o(n)$的),考虑优化:
对于所有边$(x,y,w)$,在边上新建一个点,其点权为0、到$x$距离为1、到$y$距离为$w-1$
由此,只需要求出这些新建点的$cost$即可(注意其并不影响上述分析),维护(以$x$为根后)每一个新建点子树内所有点到其距离的$\frac{3}{2}$次之和、到其距离+2的$\frac{3}{2}$次之和即可
(注意虽然重心一定在$T_{0}$中,但递归的仍是整个$T$)
时间复杂度为$o(n\log n)$,可以通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 struct Edge{
5 int nex,to,len;
6 }edge[N<<1];
7 int n,E,rt,x,y,z,a[N],head[N],sz[N],vis[N];
8 void add(int x,int y,int z){
9 edge[E]=Edge{head[x],y,z};
10 head[x]=E++;
11 }
12 void get_sz(int k,int fa){
13 sz[k]=1;
14 for(int i=head[k];i!=-1;i=edge[i].nex)
15 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
16 get_sz(edge[i].to,k);
17 sz[k]+=sz[edge[i].to];
18 }
19 }
20 void get_rt(int k,int fa,int s){
21 int mx=s-sz[k];
22 for(int i=head[k];i!=-1;i=edge[i].nex)
23 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){
24 get_rt(edge[i].to,k,s);
25 mx=max(mx,sz[edge[i].to]);
26 }
27 if (mx<=(s>>1))rt=k;
28 }
29 double get_s(int k,int fa,int s){
30 double sum=a[k]*(pow(s,1.5)-pow(s+2,1.5));
31 for(int i=head[k];i!=-1;i=edge[i].nex)
32 if (edge[i].to!=fa)sum+=get_s(edge[i].to,k,s+edge[i].len);
33 return sum;
34 }
35 double get_cost(int k,int fa=0,int s=0){
36 double sum=a[k]*pow(s,1.5);
37 for(int i=head[k];i!=-1;i=edge[i].nex)
38 if (edge[i].to!=fa)sum+=get_cost(edge[i].to,k,s+edge[i].len);
39 return sum;
40 }
41 int dfs(int k){
42 get_sz(k,0);
43 get_rt(k,0,sz[k]);
44 int pos=0;
45 double s=1;
46 for(int i=head[rt];i!=-1;i=edge[i].nex){
47 double ss=get_s(edge[i].to,rt,edge[i].len-1);
48 if (ss<s)pos=edge[i].to,s=ss;
49 }
50 if ((!pos)||(get_cost(rt)<=get_cost(pos)))return rt;
51 vis[rt]=1;
52 return dfs(pos);
53 }
54 int main(){
55 scanf("%d",&n);
56 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
57 memset(head,-1,sizeof(head));
58 for(int i=1;i<n;i++){
59 scanf("%d%d%d",&x,&y,&z);
60 add(x,y,z),add(y,x,z);
61 assert(z>=1);
62 }
63 x=dfs(1);
64 printf("%d %.7f\n",x,get_cost(x));
65 return 0;
66 }
[cf566C]Logistical Questions的更多相关文章
- CF566C Logistical Questions(10-1)
题意 \(n\)个点的树,有点权,有边权,\(f(x)=\sum\limits_{i=1}^n w_idis(i,x)^{1.5}\),求最小的\(f(x)\)的\(x\) 单独考虑一条链,顺序编号, ...
- 【CF566C】Logistical Questions 点分
[CF566C]Logistical Questions 题意:给你一棵n个点的树,点有点权,边有边权,两点间的距离为两点间的边权和的$3\over 2$次方.求这棵树的带权重心. $n\le 200 ...
- Codeforces 566C - Logistical Questions(点分治)
Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%% 首先考虑对这个奇奇怪怪的 \(t^{3/2}\) 进行一番观察.考虑构造函数 \(f(x)=ax^{3/2}+b(d-x) ...
- Diary / Solution Set -「WC 2022」线上冬眠做噩梦
大概只有比较有意思又不过分超出能力范围的题叭. 可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics 任意一个 ...
- WCF学习系列二---【WCF Interview Questions – Part 2 翻译系列】
http://www.topwcftutorials.net/2012/09/wcf-faqs-part2.html WCF Interview Questions – Part 2 This WCF ...
- [译]Node.js Interview Questions and Answers (2017 Edition)
原文 Node.js Interview Questions for 2017 什么是error-first callback? 如何避免无止境的callback? 什么是Promises? 用什么工 ...
- [面试] Design Questions
Uber总是考一些系统设计的题目,而且重复率很高,汇总了一下地里的所有design的题目,希望可以跟小伙伴们讨论下. Uber Design Questions 1. 让design uber ...
- Front End Developer Questions 前端开发人员问题(二)CSS 后续
问题来源:http://markyun.github.io/2015/Front-end-Developer-Questions/ 31.视差滚动效果,如何给每页做不同的动画?(回到顶部,向下滑动要再 ...
- WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】
http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...
随机推荐
- Java字符串的初始化与比较
Java字符串的初始化与比较 简单的总结:直接赋值而不是使用new关键字给字符串初始化,在编译时就将String对象放进字符串常量池中:使用new关键字初始化字符串时,是在堆栈区存放变量名和内容:字符 ...
- Springboot在有锁的情况下如何正确使用事务
1. 概述 老话说的好:想要赚钱,就去看看有钱人有什么需求,因为有钱人钱多,所以赚的多. 言归正传,在Java项目的研发中,"锁"这个词并不陌生,最经典的使用场景是商品的超卖问题. ...
- 字符串编码js第三方类库text-encoding
GITHUB地址:https://github.com/BCode001/text-encoding
- Golang/Java 实现无重复字符的最长子串 - LeetCode 算法
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度. 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-subs ...
- WIFI Deauth攻击-爬坑笔记
这里用Aircrack这款工具进行介绍: 准备工作:无线网卡连接电脑或者虚拟机(免驱的最好),如需驱动请自行安装驱动 1.将无线网卡接入测试电脑Linux虚拟机(装有Aircrack-ng) 2.测试 ...
- TypeScript中将函数中的局部变量“导出”的方法
首先是在模块a.js中声明一个可导出(export)的数据结构,例如: export class ModelInfo{ id: string; name:string; } 其次是在模块b中声明可导出 ...
- Spring中属性注入的几种方式以及复杂属性的注入详解
在spring框架中,属性的注入我们有多种方式,我们可以通过set方法注入,可以通过构造方法注入,也可以通过p名称空间注入,方式多种多样,对于复杂的数据类型比如对象.数组.List.Map.Prope ...
- Vue接收后端传过来excel表格的文件流并下载
题外话:当接收文件流时要确定文件流的类型,但也有例外就是application/octet-stream类型,主要是只用来下载的类型,这个类型简单理解意思就是通用类型类似 var .object.ar ...
- Noip模拟31 2021.8.5
T1 Game 当时先胡了一发$\textit{Next Permutation}$... 然后想正解,只想到贪心能求最大得分,然后就不会了.. 然后就甩个二十分的走了... 正解的最大得分(叫它$k ...
- 函数指针和qsort函数
1.函数指针的形式: 函数指针:int (*funcP) (int *a, int *b) 表示定义了一个funcP函数指针,指向了返回值为int类型,参数为int* 和int* 的函数 使用方式: ...