为什么你们常数都这么小啊

UOJ #276

题意:在树上找一条链使得|边权平均值$ -k$|尽量小,$ n<=5e4$


$ Solution:$

首先二分答案$ ans$,即我们需要找一条链使得边权平均值 $\in [-ans,ans]$

我们分正负两半分开讨论

先假设平均值$ \in (0,ans]$

将原树点分

统计过根的所有链

将这些链记录长度$len$,边数$sum$,所属子树标号$id$之后按长度排序

添加一条链$(0,0,0)$,则过某点的链一定是某两条不在同一子树的链拼接而成

两条链拼接合法当且仅当$ \frac{len_i+len_j}{sum_i+sum_j} \in (0,ans]$

化简得$ len_i+len_j>0且len_i-ans·sum_i+len_j-ans·sum_j \leq 0$

我们记录后缀$ len_i-ans·sum_i$的最小值

然后两个指针扫扫就好了

注意存在不在同一子树的限制,我们需要同时记录不在同一子树的后缀最小值和次小值,这样才能合并

如果平均值$ \in [-ans,0]$,也用同样的方法维护前缀最大值和次大值即可

注意各种边界的问题

时间复杂度:$ O(n \ log \ n \ log \ val)$


$ my \ code$

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define M 100010
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x = ; char zf = ; char ch = getchar();
while (ch != '-' && !isdigit(ch)) ch = getchar();
if (ch == '-') zf = -, ch = getchar();
while (isdigit(ch)) x = x * + ch - '', ch = getchar(); return x * zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int i,j,k,m,n,x,y,z,cnt,all,Root,nowmin;
int F[M],L[M],N[M],a[M],size[M];ll c[M];
bool vis[M];
void add(int x,int y,ll z){
a[++k]=y;c[k]=z;
if(!F[x])F[x]=k;
else N[L[x]]=k;
L[x]=k;
}
void getRoot(int x,int pre){
size[x]=;int Maxsize=;
for(rt i=F[x];i;i=N[i])if(a[i]!=pre&&!vis[a[i]]){
getRoot(a[i],x);size[x]+=size[a[i]];
Maxsize=max(Maxsize,size[a[i]]);
}
Maxsize=max(Maxsize,all-size[x]);
if(Maxsize<nowmin)nowmin=Maxsize,Root=x;
}
int cs;
vector<int>e[];
void build(int x){
int ls=all;vis[x]=;
for(rt i=F[x];i;i=N[i])if(!vis[a[i]]){
all=(size[a[i]]>size[x]?ls-size[x]:size[a[i]]);
nowmin=;Root=;getRoot(a[i],x);
e[x].push_back(Root);
build(Root);
}
}
struct chain{
ll len;int sl,col;
bool operator <(const chain s)const{
return len<s.len;
}
}q[];int t;
void Add(int col,int x,int pre,ll len,int sl){
q[++t]={len,sl,col};
for(rt i=F[x];i;i=N[i])if(a[i]!=pre&&!vis[a[i]])Add(col,a[i],x,len+c[i],sl+);
}
int qzmax[][],hzmin[][],allsize=;
bool check(int x,ll ans){//0...x
q[t=]={,,};vis[x]=;
for(rt i=F[x];i;i=N[i])if(!vis[a[i]])Add(a[i],a[i],x,c[i],);
sort(q+,q+t+);
qzmax[][]=;qzmax[][]=;
for(rt i=;i<=t;i++){
int id0=qzmax[i-][],id1=qzmax[i-][];
qzmax[i][]=id0;qzmax[i][]=id1;
if(q[i].len+ans*q[i].sl>q[id0].len+ans*q[id0].sl){
if(q[i].col!=q[id0].col)qzmax[i][]=qzmax[i][];
qzmax[i][]=i;
}
else if(q[i].len+ans*q[i].sl>q[id1].len+ans*q[id1].sl||!id1){
if(q[i].col!=q[id0].col)qzmax[i][]=i;
}
}
hzmin[t][]=t;hzmin[t][]=;
for(rt i=t-;i>=;i--){
int id0=hzmin[i+][],id1=hzmin[i+][];
hzmin[i][]=id0;hzmin[i][]=id1;
if(q[i].len-ans*q[i].sl<q[id0].len-ans*q[id0].sl){
if(q[i].col!=q[id0].col)hzmin[i][]=hzmin[i][];
hzmin[i][]=i;
}
else if(q[i].len-ans*q[i].sl<q[id1].len-ans*q[id1].sl||!id1){
if(q[i].col!=q[id0].col)hzmin[i][]=i;
}
}
int R=t;
for(rt i=;i<=t;i++){
while((q[i].len+q[R].len>||R==i)&&R)R--;
if(R==)break;if(R>=i)continue;
int maxv=qzmax[R][];
if(q[qzmax[R][]].col==q[i].col)maxv=qzmax[R][];
if(maxv==)continue;
if(q[i].len+q[i].sl*ans+q[maxv].len+ans*q[maxv].sl>)return ;
}
int L=;
for(rt i=t;i>=;i--){
while((q[i].len+q[L].len<||L==i)&&L<=t)L++;
if(L>t)break;if(L<=i)continue;
int minv=hzmin[L][];
if(q[hzmin[L][]].col==q[i].col)minv=hzmin[L][];
if(!minv)continue;
if(q[i].len-q[i].sl*ans+q[minv].len-ans*q[minv].sl<)return ;
}
bool res=;
for(rt i=;i<e[x].size();i++)if(!res)res|=check(e[x][i],ans);
return res;
}
int main(){
n=read();ll w=read();
for(rt i=;i<n;i++){
x=read();y=read();ll z=read();
add(x,y,z-w);
add(y,x,z-w);
}
nowmin=;all=n;getRoot(,);
int troot=Root;build(Root);
memset(vis,,sizeof(vis));
ll L=,R=;
while(L<=R){
memset(vis,,sizeof(vis));
ll mid=(L+R)/;
if(check(troot,mid))R=mid-;
else L=mid+;
}
write(R);
return ;
}

UOJ #276「清华集训2016」汽水的更多相关文章

  1. [UOJ#276]【清华集训2016】汽水

    [UOJ#276][清华集训2016]汽水 试题描述 牛牛来到了一个盛产汽水的国度旅行. 这个国度的地图上有 \(n\) 个城市,这些城市之间用 \(n−1\) 条道路连接,任意两个城市之间,都存在一 ...

  2. UOJ#276. 【清华集训2016】汽水 二分答案 点分治

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ276.html 题解 首先,读入的时候就将所有的 $w_i$ 减掉 $k$ . 于是我们要求的就是平均值最 ...

  3. uoj#276. 【清华集训2016】汽水(分数规划+点分治)

    传送门 没想到点分治那一层-- 首先不难发现这是个分数规划,先把所有的边长减去\(k\),二分答案,设为\(mid\),就是要求路径平均值\(ans\in[-mid,mid]\) 先来考虑\(ans\ ...

  4. UOJ #36「清华集训2014」玛里苟斯

    这怎么想得到啊......... UOJ #36 题意:求随机一个集合的子集的异或和的$k$次方的期望值,保证答案$ \lt 2^{63},1 \leq k \leq 5$ $ Solution:$ ...

  5. UOJ #2321. 「清华集训 2017」无限之环

    首先裂点表示四个方向 一条边上都有插头或者都不有插头,相当于满足流量平衡 最大流 = 插头个数*2时有解 然后求最小费用最大流 黑白染色分别连原点汇点

  6. UOJ 275. 【清华集训2016】组合数问题

    UOJ 275. [清华集训2016]组合数问题 组合数 $C_n^m $表示的是从 \(n\) 个物品中选出 \(m\) 个物品的方案数.举个例子,从$ (1,2,3)(1,2,3)$ 三个物品中选 ...

  7. UOJ #269. 【清华集训2016】如何优雅地求和

    UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...

  8. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  9. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

随机推荐

  1. Java 对远程文件的操作

    首先添加jar <dependency> <groupId>jcifs</groupId> <artifactId>jcifs</artifact ...

  2. luogu4211 LCA

    题目链接 思路 我们换一种求\(dep[lca(i,j)]\)的方法. 将从根到\(i\)的路径上所有点的权值加\(1\),然后求从根节点到j路径上点的权值和.就是\(i\)和\(j\)的\(lca\ ...

  3. 四种不同的SNP calling算法call低碱基覆盖度测序数据时,SNVs数量的比较(Comparing a few SNP calling algorithms using low-coverage sequencing data)

    摘要:如果不设置任何过滤标准的话,SOAPsnp会call出更多的SNVs:AtlasSNP2算法比较严格,因此call出来的SNVs数量是最少的,GATK 和 SAMtools call出来的数量位 ...

  4. Day27--Python--初识socket

    一. C\S架构, 客户端服务端架构 客户端(client): 享受服务端提供的服务 服务端(server): 给客户端提供服务 B\S 浏览器和服务端 B (browser) 二. 网络通信的整个流 ...

  5. 对C# .Net4.5异步机制测试

    static void Main(string[] args) { Test(); // 这个方法其实是多余的, 本来可以直接写下面的方法 // await GetName() // 但是由于控制台的 ...

  6. eclipse+pyDev

    感觉python脚本语言在linux下挺有用的,想入门学习一下 新手入门个人习惯找个好点的IDE帮助完成工作,试了好多,如pycharm,sublime text自己打造 后来发现全扯淡,一点不符合自 ...

  7. i2c框架

    目录 i2c框架 寄存器 主机发送 主机接收 中断处理 程序框架 title: iic框架 tags: ARM date: 2018-11-05 13:44:58 --- i2c框架 寄存器 /* 配 ...

  8. ATPCS规则

    title: ATPCS规则 tags: ARM date: 2018-10-14 17:03:23 --- ATPCS规则 ARM指令集E004armproc.chm ATPCS介绍与使用.pdf ...

  9. JAVA核心技术I---JAVA基础知识(回顾)

    一:对象实例化问题: public class Rectangle { ; ; public int area() { return width * height; } } 则如下代码输出结果为: R ...

  10. ThinkPHP3.2中字段unique验证出错的解决方法

    protected $_validate=array( array('stu_id','','学号已存在',1,'unique',1), ) 当一次插入多条数据时: 在进行循环 使用create验证时 ...