解题:NOI 2014 购票
观察一下部分分,我们发现链上的部分分是这样一个DP:
$dp[i]=min(dp[i],dp[j]+dis(i,j)*p[i]+q[i])(dis(i,j)<=lim[i]\&\&j∈anc(i))$
对于可以对$i$转移的两个位置$j$和$k$,假设$dep[j]>dep[k]$且$j$比$k$优,那么倒腾一下式子
$dp[j]+dis(i,j)*p[i]+q[i]<dp[k]+dis(i,k)*p[i]+q[i]$
$dp[j]-dp[k]<(dis(i,k)-dis(i,j))*p[i]$
$\frac{dp[j]-dp[k]}{dis(i,k)-dis(i,j)}<p[i]$
因为$dis$是单调的,这个东西可以使用斜率优化,因为$p[i]$不单调每次需要二分来转移
然后问题来了,现在不是棵树,如果提出来每条链来做是O(叶子数*len)的,会被扫帚图卡掉,于是有了各种优化来做这道题:
Sol1:用轻重链剖分优化,直接以一个log的代价把整条链拼出来,再用一个log的数据结构维护,复杂度$O(n\log^3 n)$
Sol2:用可持久化数据结构维护单调队列或者用待撤销的二进制分组,利用上面一段已经处理好的链分别处理每个叶子,只需要一个log,复杂度$O(n\log^2 n)$
Sol3(我写的这个):不用数据结构维护,用点分治的方法,每次把重心和它子树外的部分递归处理,然后DFS重心的子树,子树里的节点按向上延伸后的深度排序后DP,之后再处理每一棵子树。排序和DP的log是并列的,复杂度$O(n\log^2 n)$
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,inf=1e9;
int n,t,c,cnt,top,tpp,tsiz,maxx;
int fth[N],p[N],noww[N],goal[N],siz[N],vis[N],stk[N],sta[N];
long long len[N],val[N],dis[N],pr1[N],pr2[N],lim[N],dp[N],rd;
bool cmp(int a,int b)
{
return dis[a]-lim[a]>dis[b]-lim[b];
}
double Slope(int a,int b)
{
return (double)(dp[b]-dp[a])/(double)(dis[b]-dis[a]);
}
void Link(int f,int t,long long v)
{
noww[++cnt]=p[f],p[f]=cnt;
goal[cnt]=t,val[cnt]=v;
}
void Getdis(int nde)
{
for(int i=p[nde];i;i=noww[i])
dis[goal[i]]=dis[nde]+val[i],Getdis(goal[i]);
}
void Mark(int nde,int sze)
{
siz[nde]=; int tmp=;
for(int i=p[nde];i;i=noww[i])
if(!vis[goal[i]])
{
Mark(goal[i],sze);
siz[nde]+=siz[goal[i]];
tmp=max(tmp,siz[goal[i]]);
}
tmp=max(tmp,sze-siz[nde]);
if(tmp<=maxx) maxx=tmp,c=nde;
}
void DFS(int nde)
{
stk[++top]=nde;
for(int i=p[nde];i;i=noww[i])
if(!vis[goal[i]]) DFS(goal[i]);
}
void DP(int nde,int anc)
{
for(int i=;i<=top;i++)
{
int nod=stk[i];
while(nde!=fth[anc]&&dis[nod]-dis[nde]<=lim[nod])
{
while(tpp>=&&Slope(sta[tpp],nde)>=Slope(sta[tpp-],sta[tpp]))
tpp--; sta[++tpp]=nde,nde=fth[nde];
}
if(tpp)
{
int l=,r=tpp,best;
while(l<=r)
{
int mid=(l+r)/;
double s=(mid==tpp)?-inf:Slope(sta[mid],sta[mid+]);
if(s<=pr1[nod]) r=mid-,best=mid; else l=mid+;
}
best=sta[best],dp[nod]=min(dp[nod],dp[best]+(dis[nod]-dis[best])*pr1[nod]+pr2[nod]);
}
}
}
void PDC(int nde,int sze)
{
if(sze<=) return;
maxx=inf,Mark(nde,sze); int hc=c;
for(int i=p[hc];i;i=noww[i])
vis[goal[i]]=true,sze-=siz[goal[i]];
PDC(nde,sze),top=;
for(int i=p[hc];i;i=noww[i]) DFS(goal[i]);
sort(stk+,stk++top,cmp),tpp=,DP(hc,nde);
for(int i=p[hc];i;i=noww[i]) PDC(goal[i],siz[goal[i]]);
}
int main()
{
scanf("%d%d",&n,&t);
for(int i=;i<=n;i++)
{
scanf("%d%lld",&fth[i],&rd),Link(fth[i],i,rd);
scanf("%lld%lld%lld",&pr1[i],&pr2[i],&lim[i]),dp[i]=1e18;
}
Getdis(),PDC(,n);
for(int i=;i<=n;i++) printf("%lld\n",dp[i]);
return ;
}
解题:NOI 2014 购票的更多相关文章
- BZOJ 3672 NOI 2014 购票
题面 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市 ...
- [luogu P2375] [NOI 2014] 动物园
[luogu P2375] [NOI 2014] 动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向 ...
- 【BZOJ 3672】【UOJ #7】【NOI 2014】购票
http://www.lydsy.com/JudgeOnline/problem.php?id=3672 http://uoj.ac/problem/7 链上的情况可以用斜率优化dp.树上用斜率优化d ...
- 解题:NOI 2014 随机数生成器
题面 为什么NOI2014有模拟题=.=??? 按题意把序列生成出来之后,对每一行维护一个能取到的最左侧和能取到的最右侧.从小到大$O(n^2)$枚举数字看看能否填入,能填入则暴力$O(n)$更新信息 ...
- 解题:NOI 2014 动物园
题面 其实好像并不难,因为猫老师(应该是猫老师吧,还是LX大佬?)有一句话让我印象深刻:“包的(border)的包的还是包的”=.= 统计个数不就是统计长度么,然后根据上面那句话,当$nxt$长度大于 ...
- [NOI 2014]魔法森林
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- [NOI 2014]做题记录
[NOI2014]起床困难综合症 按位贪心 #include <algorithm> #include <iostream> #include <cstring> ...
- NOI 2014 感想
NOI2014结束了,我卡线登上了领奖台... 这是我第一次NOI,我觉得我收获了很多东西: 1.考前心态不重要,重要的是实力 真正考试的时候是顾不得想其他事情的 2.测试数据是人出的!不是随机的!不 ...
- NOI 2014简要题解
Day 1.Problem A. 起床困难综合症 100分做法: 把数字看成二进制数.对于初始攻击力.我们将其拆成32位,并求出每一位为0和1时经过全部防御门之后分别得到的数字.然后就是按位贪心了,我 ...
随机推荐
- linux运维升级路线
运维工程师是从一个呆逼进化为苦逼再成长为牛逼的过程,前提在于你要能忍能干能拼,还要具有敏锐的嗅觉感知前方潮流变化.如:今年大数据,人工智能比较火……(相对表示就是 Python 比较火) 之前写过运维 ...
- Go入门指南
第一部分:学习 Go 语言 第1章:Go 语言的起源,发展与普及 1.1 起源与发展 1.2 语言的主要特性与发展的环境和影响因素 第2章:安装与运行环境 2.1 平台与架构 2.2 Go 环境变量 ...
- ipmitool命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/EricDing/p/8995263.html [root@localhost ~]# yum install -y i ...
- 团队项目之开题scrum meeting
scrum meeting 会议记 一.会议要点: 1.确定成员角色: 2.讨论关于项目的疑问: 3.制定一周内成员任务. 二.具体会议内容: 1.成员角色: PM:杨伊 Dev:徐钧鸿 刘浩然 张艺 ...
- 20172321 20172333 2017-2018 暑假作业APP
20172321 20172333 2017-2018 暑假作业APP 项目介绍 项目成员 吴恒佚 20172321 严域俊 20172333 项目简介 从理论上来说,这是一个贪吃蛇游戏. <贪 ...
- cnblogs.com用户体验
一.是否提供了良好的体验给用户(同时提供价值)? 首先我觉得博客园给我们这些用户提供了良好的用户体验,博客园提供了一个纯净的技术交流空间,在这里我们可以找到几乎所有与IT技术有关的博文,而且可以在这里 ...
- 软件项目的开发之svn的使用
Svn简介 SVN全名Subversion,即版本控制系统.SVN与CVS一样,是一个跨平台的软件,支持大多数常见的操作系统.作为一个开源的版本控制系统,Subversion管理着随时间改变的数据.这 ...
- wamp 修改www目录
我的情况 Wamp版本:2.2 WAMP2.2安装目录:C:/ www目录:D:/wamp/www/ 变更目录:E:/HbuilderProjects/ 一 主要过程: (1)修改 D:\wamp\b ...
- java中的互斥锁和信号量的区别
互斥锁和信号量都是操作系统中为并发编程设计基本概念,互斥锁和信号量的概念上的不同在于,对于同一个资源,互斥锁只有0和1 的概念,而信号量不止于此.也就是说,信号量可以使资源同时被多个线程访问,而互斥锁 ...
- 实现二叉树(search)
★实验任务 可怜的 Bibi 刚刚回到家,就发现自己的手机丢了,现在他决定回头去搜索 自己的手机. 现在我们假设 Bibi 的家位于一棵二叉树的根部.在 Bibi 的心中,每个节点 都有一个权值 x, ...