BZOJ

UOJ


记\(val_i\)是每条边的边权,\(s\)是边权和,\(t\)是经过边数,\(k\)是给定的\(k\)。

在点分治的时候二分答案\(x\),设\(|\frac st-k|=x\),判断是否还能满足\(|\frac st-k|<x\)。

因为是绝对值,分两种情况:

  1. \(\frac st-k\geq 0\to \sum val_i-k\geq 0\),

    判断是否有\(\frac st-k< x\to\quad s-t*k<t*x\to\quad\sum val_i-k<t*x\)。
  2. \(\frac st-k<0\to\sum val_i-k<0\),

    判断是否有\(\frac st-k>-x\to\quad s-t*k>-t*x\to\quad \sum val_i-k>-t*x\)

先对每条边的边权\(val_i\)减掉一个\(k\)。

以第一种情况为例,就是求是否存在两条路径\(i,j\),使得\(s_i+s_j\geq 0\),且\(s_i+s_j<t_i*x+t_j*x\)。

把\(DFS\)得到的子树路径信息存一个三元组\((s,t,anc)\),表示一条路径的权值和、边数、这条路径来自哪棵子树(两条路径拼起来的时候不能来自同一棵子树)。

然后把所有三元组按\(s\)从小到大排序。那从小到大枚举\(i\),第一个满足\(s_i+s_j\geq 0\)的\(j\)的位置一定是单调递减的,\(j\)后面(\(i\)之前)的路径都满足。

所以维护两个\(pair\),表示两个\(s_k-t_k*x\)最小的、来自不同子树的三元组\(A,B\)。找到第一个\(s_p>0\)的位置\(p\),令\(i=p,j=p-1\),然后随着\(i\)的枚举,更新一下\(A,B\),然后\(j\)也不断往前移动顺便更新\(A,B\)就可以了。每次对于\(i\),就把\(A,B\)做\(k\),与\(i\)组合一下看是否可以满足\(s_k-t_k*x<t_i*x-s_i\)。

具体看代码吧,

有两种情况就二分\(x\)的时候,用两个\(check\)判断\(x\)(\(\frac st -k\geq 0\))和\(-x\)(\(\frac st-k<0\))是否有一个可行就行了。

都是抄的一份代码 常数差距怎么就那么大呢


//6952kb	6680ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define mp std::make_pair
#define pr std::pair<LL,int>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=5e4+5;
const LL INF=1ll<<60; int cnt,Enum,H[N],nxt[N<<1],to[N<<1],Min,root,sz[N];
LL Ans,len[N<<1];
bool vis[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Node
{
LL s; int t,anc;
inline bool operator <(const Node &x)const
{
return s<x.s;
}
}A[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline LL readll()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(LL w,int u,int v)
{
Ans=std::min(Ans,std::abs(w));//abs!!!
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
}
void FindRoot(int x,int fa,int tot)
{
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]]&&v!=fa)
FindRoot(v,x,tot), sz[x]+=sz[v], sz[v]>mx&&(mx=sz[v]);
mx=std::max(mx,tot-sz[x]);
if(mx<Min) Min=mx, root=x;
}
void DFS(int x,int fa,LL s,int dep,int anc)
{
A[++cnt]=(Node){s,dep,anc};
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]] && v!=fa) DFS(v,x,s+len[i],dep+1,anc);
}
inline void Upd(pr &x,pr &y,pr now)
{
if(now.first<y.first)
{
if(now.first<x.first)
{
if(now.second!=x.second) y=x;
x=now;
}
else if(now.second!=x.second) y=now;
}
}
bool Check1(LL k,int pos,int cnt)
{
pr x(INF,0),y(INF,0); A[0].s=-INF;
for(int i=pos,j=pos-1; i<=cnt; ++i)
{
while(A[i].s+A[j].s>=0) Upd(x,y,mp(A[j].s-k*A[j].t,A[j].anc)), --j;
if((x.second==A[i].anc?y.first:x.first)+A[i].s<k*A[i].t) return 1;
Upd(x,y,mp(A[i].s-k*A[i].t,A[i].anc));
}
return 0;
}
bool Check2(LL k,int pos,int cnt)
{//s>-tx -> -s<tx
pr x(INF,0),y(INF,0); A[cnt+1].s=INF;
for(int i=pos-1,j=pos; i; --i)
{
while(A[i].s+A[j].s<0) Upd(x,y,mp(-A[j].s-k*A[j].t,A[j].anc)), ++j;
if((x.second==A[i].anc?y.first:x.first)-A[i].s<k*A[i].t) return 1;
Upd(x,y,mp(-A[i].s-k*A[i].t,A[i].anc));
}
return 0;
}
void Solve(int x)
{
vis[x]=1, A[cnt=1]=(Node){0,0,0};
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]]) DFS(v,x,len[i],1,v);
int p=1; std::sort(A+1,A+1+cnt), A[cnt+1].s=0;
while(A[p].s<0) ++p;
LL l=1,r=Ans,mid;//判断是否存在比Ans小的答案 范围是1~Ans!(UOJ数据真心强=-=)
while(l<=r)
if(Check1(mid=l+r>>1,p,cnt)||Check2(mid,p,cnt)) Ans=mid-1, r=mid-1;
else l=mid+1;
for(int i=H[x],v; i; i=nxt[i])
if(!vis[v=to[i]]) Min=N, FindRoot(v,x,sz[v]), Solve(root);
} int main()
{
const int n=read(); const LL K=readll();//readll!!
Ans=INF;//在这 不能在Solve()前面 = =
for(int i=1; i<n; ++i) AE(readll()-K,read(),read());
Min=N, FindRoot(1,1,n), Solve(root);
printf("%lld\n",Ans); return 0;
}

BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)的更多相关文章

  1. [UOJ#276][清华集训2016]汽水[分数规划+点分治]

    题意 给定一棵 \(n\) 个点的树,给定 \(k\) ,求 \(|\frac{\sum w(路径长度)}{t(路径边数)}-k|\)的最小值. \(n\leq 5\times 10^5,k\leq ...

  2. UOJ276 [清华集训2016] 汽水 【二分答案】【点分治】【树状数组】

    题目分析: 这种乱七八糟的题目一看就是点分治,答案有单调性,所以还可以二分答案. 我们每次二分的时候考虑答案会不会大于等于某个值,注意到系数$k$是无意义的,因为我们可以通过转化使得$k=0$. 合并 ...

  3. 并不对劲的uoj276. [清华集训2016]汽水

    想要很对劲的讲解,请点击这里 题目大意 有一棵\(n\)(\(n\leq 50000\))个节点的树,有边权 求一条路径使该路径的边权平均值最接近给出的一个数\(k\) 输出边权平均值下取整的整数部分 ...

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

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

  5. bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct

    [清华集训2016]温暖会指引我们前行 统计 描述 提交 自定义测试 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了 ...

  6. UOJ #274. 【清华集训2016】温暖会指引我们前行 [lct]

    #274. [清华集训2016]温暖会指引我们前行 题意比较巧妙 裸lct维护最大生成树 #include <iostream> #include <cstdio> #incl ...

  7. UOJ_274_[清华集训2016]温暖会指引我们前行_LCT

    UOJ_274_[清华集训2016]温暖会指引我们前行_LCT 任务描述:http://uoj.ac/problem/274 本题中的字典序不同在于空串的字典序最大. 并且题中要求排序后字典序最大. ...

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

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

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

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

随机推荐

  1. uva11426 欧拉函数应用,kuangbin的筛法模板

    /* 给定n,对于所有的对(i,j),i<j,求出sum{gcd(i,j)} 有递推式sum[n]=sum[n-1]+f[n] 其中f[n]=gcd(1,n)+gcd(2,n)+gcd(3,n) ...

  2. 在lnmp环境下,将原来的PHP7.0升级到PHP7.2

    基础环境: 系统:centos6.8   环境:lnmp 停止PHP7.0的版本,在做如下操作: 1.下载php-7.2.6.tar.bz2软件包放在/opt 路径下 mkdir /usr/local ...

  3. spring cloud Hystrix监控面板Hystrix Dashboard和Turbine

    我们提到断路器是根据一段时间窗内的请求情况来判断并操作断路器的打开和关闭状态的.而这些请求情况的指标信息都是HystrixCommand和HystrixObservableCommand实例在执行过程 ...

  4. Just oj 2018 C语言程序设计竞赛(高级组)H: CBT?

    H: CBT? 时间限制: 1 s      内存限制: 128 MB      提交 我的状态 题目描述 对于二叉树,如果这棵树的节点排布是按行从上到下,每行从左到右挨个放置,中间不会有空闲的节点. ...

  5. 发布WebApi项目时,提示未包含bin\yourDocumentationFile.xml文档文件

    Open your publishprofile (*.pubxml) and include this code into "Project" element: <Item ...

  6. Elasticsearch snapshot 备份的使用方法 【备忘】

    常见的数据库都会提供备份的机制,以解决在数据库无法使用的情况下,可以开启新的实例,然后通过备份来恢复数据减少损失.虽然 Elasticsearch 有良好的容灾性,但由于以下原因,其依然需要备份机制. ...

  7. 自定义Spring标签

    写了好几次了,结果一段时间之后就忘记了自己有写好的example,但是最后还是决定重新写一遍,把这个步骤记录下来 首先看整个项目结构 从transaction.xml开始,虽然图上报错了,实际上运行并 ...

  8. Java基础知识➣发送Emai和访问MySQL数据库(七)

    概述 Java程序发送 E-mail 十分简单,但是首先你应该在你的机器上安装 JavaMail API 和Java Activation Framework (JAF) .Java访问数据则需要 使 ...

  9. python从零安装

    一 python 1.安装python https://www.python.org/ 环境变量path添加 ;C:\Python27;C:\Python27\Lib\site-packages;C: ...

  10. EF 数据版本号,处理具体使用方法 RowVersion / Timestamp 使用方法。进行自动处理并发修改

    /* * <div class="form-group"> // 原始 * <div class="form-group hidden"> ...