首页 技术 正文
技术 2022年11月16日
0 收藏 409 点赞 3,103 浏览 2737 个字

题目分析:

这种乱七八糟的题目一看就是点分治,答案有单调性,所以还可以二分答案。

我们每次二分的时候考虑答案会不会大于等于某个值,注意到系数$k$是无意义的,因为我们可以通过转化使得$k=0$。

合并的过程相当于很多个向量,加起来后看斜率。

注意单个向量也要判定。

由于有了二分的答案$Ans$。判定变得简单多了,推一下。

令$(A,C)$是从一个点到重心的一个向量,$(B,D)$是从另一个点到重心的向量。其中$A$和$B$是重心到该点的路径权值和,$C$和$D$是经过的边数。

$-k \leq \frac{A+C}{B+D} \leq k \Rightarrow -k(B+D) \leq A+C \leq k(B+D)$.

进一步的$A+kB \geq -C-kD$且$A-kB \leq kD-C$。虽然有四元,但是顺序相互关联,所以实际只有两元,排序后树状数组就可以解决啦。

 #include<bits/stdc++.h>
using namespace std; typedef long long ll; const int maxn = ; ll k,md; int flag = ,num,n,rnum;
vector <pair<int,ll> > g[maxn];
int arr[maxn],sz[maxn],imp[maxn],cnt[maxn];
struct node{ll A;int B,pla;}op[maxn]; int cmp(node X,node Y){
return -X.A-md*X.B < -Y.A-md*Y.B;
} struct Fenwick{
int C[maxn];
void Add(int now){
while(now <= rnum){C[now] ++; now += (now&-now);}
}
int query(int now){
int ans = ;
while(now){ans += C[now]; now -= (now&-now);}
return ans;
}
}T1; void read(){
scanf("%d%lld",&n,&k);
for(int i=;i<n;i++){
int x,y;long long v; scanf("%d%d%lld",&x,&y,&v); v -= k;
g[x].push_back(make_pair(y,v)); g[y].push_back(make_pair(x,v));
}
} void dfs1(int now,int fa,int dp){
sz[now] = ;imp[now] = ;
for(auto it : g[now]){
if((arr[it.first] && arr[it.first] < dp) || fa == it.first) continue;
dfs1(it.first,now,dp); sz[now] += sz[it.first];
}
} int dfs2(int now,int fa,int dp,int ssz){
int ans = ;
for(auto it : g[now]){
if((arr[it.first] && arr[it.first] < dp) || fa == it.first) continue;
int data = dfs2(it.first,now,dp,ssz);
if(ans== || imp[ans] > imp[data])ans = data;
imp[now] = max(sz[it.first],imp[now]);
}
imp[now] = max(imp[now],ssz-sz[now]);
if(ans== || imp[ans] > imp[now]) ans = now;
return ans;
} void dfs3(int now,int fa,int dp,int A,int B){
for(auto it : g[now]){
if(it.first == fa || (arr[it.first] && arr[it.first] < dp)) continue;
op[++num] = (node){A+it.second,B+,it.first};
dfs3(it.first,now,dp,A+it.second,B+);
}
} long long lisan[maxn];
void solve(int dr){
rnum = num;
for(int i=;i<=num;i++){lisan[i] = -op[i].A+md*op[i].B;}
sort(lisan+,lisan+num+);rnum = unique(lisan+,lisan+num+)-lisan-;
for(int i=;i<=rnum;i++) T1.C[i]=;
for(int i=num,j=;i>=;i--){
while(j <= num && (-op[j].A-md*op[j].B < op[i].A+md*op[i].B)){
T1.Add(lower_bound(lisan+,lisan+rnum+,-op[j].A+md*op[j].B)-lisan);
j++;
}
int ans=j--T1.query(upper_bound(lisan+,lisan+rnum+,op[i].A-md*op[i].B)-lisan-);
if(op[i].A-md*op[i].B < -op[i].A+md*op[i].B && j > i)ans--;
if(dr == ){
if(ans - cnt[op[i].pla]){flag = ;return;}
}else{cnt[op[i].pla] = ans;}
}
} void divide(int now,int dp,int lst,long long AA){
dfs1(now,,dp); int heavy = dfs2(now,,dp,sz[now]);arr[heavy] = dp;
for(auto it : g[heavy]){
if(arr[it.first]&&arr[it.first]<dp) continue;
divide(it.first,dp+,heavy,it.second);
if(flag == ) return;
}
num = ; dfs3(heavy,,dp,,); sort(op+,op+num+,cmp);
solve(); num = ;
if(lst) {
num = ;dfs3(now,,dp,AA,);
sort(op+,op+num+,cmp);
for(int i=;i<=num;i++) cnt[op[i].pla] = ;
solve();
}
} void work(){
long long l = ,r = 1e13;
while(l < r){
md = (l+r)/; flag = ;
memset(arr,,sizeof(arr));
divide(,,,);
if(flag) r = md; else l = md+;
}
printf("%lld",l-);
} int main(){
read();
work();
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848