解题: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时经过全部防御门之后分别得到的数字.然后就是按位贪心了,我 ...
随机推荐
- Netty源码分析第7章(编码器和写数据)---->第5节: Future和Promies
Netty源码分析第七章: 编码器和写数据 第五节: Future和Promise Netty中的Future, 其实类似于jdk的Future, 用于异步获取执行结果 Promise则相当于一个被观 ...
- HackRF 无线门铃信号录制与重放
本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...
- 图片人脸检测(OpenCV版)
图片人脸检测 人脸检测使用到的技术是OpenCV,上一节已经介绍了OpenCV的环境安装,点击查看. 功能展示 识别一种图上的所有人的脸,并且标出人脸的位置,画出人眼以及嘴的位置,展示效果图如下: 多 ...
- OO第三阶段作业总结
调研: 最早的程序设计是直接采用机器语言来编写的,或者使用二进制码来表示机器能够识别和执行的指令和数据.机器语言的优点在于速度快,缺点在于写起来实在是太困难了,编程效率低,可读性差,并且 ...
- vim相关命令单独记载
1. 无敌的可扩展性 1.1 可扩展性给了软件强大的生命 曾几何时,Windows用户对软件的可扩展性没有概念,他们只能对他们使用的软件进行非常有限的定制.扩展软件的权利保留在软件开发者手中.软件的使 ...
- Java面向对象程序设计
北京电子科技学院(BESTI) 实 ...
- 【CSAPP笔记】4. 汇编语言——基础知识
程序的机器级表示 计算机能读懂是机器代码(machine code)-- 用字节序列编码的低级操作 -- 也就是0和1.编译器基于编程语言的规则.目标机器的指令集和操作系统的规则,经过一系列阶段产生机 ...
- 四则运算web版
1)在文章开头给出Coding.Net项目地址.(1') https://git.coding.net/meiyoupiqidefan/jieduizuoye.git url测试地址:http://3 ...
- C++编译与链接(1)-编译与链接过程
大家知道计算机使用的一系列的1和0 那个一个C++语言程序又是如何从一个个.h和.cpp文件变成包含1和0的可执行文件呢? 可以认为有以下的几个环节 源程序->预处理->编译和优化-> ...
- Android之自定义View学习(一)
Android之自定义View学习(一) Canvas常用方法: 图片来源 /** * Created by SiberiaDante on 2017/6/3. */ public class Bas ...