「IOI2009」旅行商
首先,看到这道题感觉就像dp(然鹅没什么用)。
一个美好的设想
假如没有两个展销会在同一天开展:前途光明
暴力dp,复杂度o(\(n^2\))。
没有同一天的展销会
暴力dp慢,是因为本质上很多状态都是没有什么用的(或者说可以压缩)。
那么可以考虑将一个区间的信息压缩到点上。

先把一段区间均分为左半部分和右半部分。
假如A这个点有展销会,那么左半部分就会向右走。
考虑把左半部分的信息压缩到端点,这个还是比较简单的,如果左半部分有开展过展销会,那么顺便把左右端点的值给更新掉。这样就快速的将左半部分的值转移到A点。

再转到剩下右半部分。
继续把区间切成两半,同理将右半部分的信息转移到A点,对左半部分进行递归处理。
那么现在假设A点已经处理好了。要进行信息的更新。
首先,左右端点肯定是需要的。对于切割点同样也要更新(仅仅更新左右端点是无法处理这种情况的)。
于是一个展销会就被处理好了,一次的复杂度为o(log(n))。
有同一天的展销会
还是要面对有展销会在同一天的事实。。。
其实,同一天的展销会可以按照所在位置进行排序,然后按照某个顺序dp下去(我总不可能先←再→然后←,明显的浪费钱),所以只要正序,倒序各自dp一遍即可。
然而信息不能相互干扰,所以需要一个中间数组来存储某一个顺序的dp结果(当然不需要全部的信息,只需要展销会所在的点,再另行更新),而另一顺序直接放到原数组里就好了。
由于这个写法保证了每个点都会包括到一个或多个可以更新答案的点(并且保证可以以最优的方式转移),所以直接按顺序dp下来并没有什么问题(相当于先移动到一个点,再单方向移动,囊括了 先←再→ 以及 先→再← 的方案)。所以70pts和100pts思路没有区别。
这样这道题就好了 (假装讲明白了)。
code
#include<bits/stdc++.h>
#define unable AC
#define KLL dying
#define re register int
#define rep(q,a,b) for(re q(a),q##_end_(b);q<=q##_end_;++q)
#define dep(q,a,b) for(re q(a),q##_end_(b);q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
void in(int &r) {
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
const int mn=500005;
int val[mn],n,n_cost,s_cost,st;
struct node {
int tim,at,val;
bool operator <(const node &A)const {
return tim==A.tim?at<A.at:tim<A.tim;
}
} qw[mn];
int len_max,Max,at,adv,md[mn];
int dis(int l,int r) {
if(l<r)return (r-l)*s_cost;
return (l-r)*n_cost;
}
void mid_add(int l,int r) {
md[l]=max(md[l],val[l]),md[r]=max(md[r],val[r]);
if(l==r)md[l]=max(md[l],Max+adv);
else {
Max=max(Max,md[l]-dis(l,at));
Max=max(Max,md[r]-dis(r,at));
int mid=l+r>>1;
if(at>mid) {
mid_add(mid+1,r);
md[mid]=max(md[mid],val[mid]);
md[mid]=max(md[mid],md[at]-dis(at,mid));
} else {
mid_add(l,mid);
md[mid+1]=max(md[mid+1],val[mid+1]);
md[mid+1]=max(md[mid+1],md[at]-dis(at,mid+1));
}
md[l]=max(md[l],md[at]-dis(at,l));
md[r]=max(md[r],md[at]-dis(at,r));
}
}
void add(int l,int r) {
if(l==r)val[l]=max(val[l],Max+adv);
else {
Max=max(Max,val[l]-dis(l,at));
Max=max(Max,val[r]-dis(r,at));
int mid=l+r>>1;
if(at>mid) {
add(mid+1,r);
val[mid]=max(val[mid],val[at]-dis(at,mid));
} else {
add(l,mid);
val[mid+1]=max(val[mid+1],val[at]-dis(at,mid+1));
}
val[l]=max(val[l],val[at]-dis(at,l));
val[r]=max(val[r],val[at]-dis(at,r));
}
}
void replace(int l,int r) {
if(l==r)val[l]=max(val[l],adv);
else {
int mid=l+r>>1;
if(at>mid) {
replace(mid+1,r);
val[mid]=max(val[mid],val[at]-dis(at,mid));
} else {
replace(l,mid);
val[mid+1]=max(val[mid+1],val[at]-dis(at,mid+1));
}
val[l]=max(val[l],adv-dis(at,l));
val[r]=max(val[r],adv-dis(at,r));
}
}
void solve() {
rep(q,1,len_max)val[q]=-dis(st,q),md[q]=val[q];
int now=1;
while(now<=n) {
int last=now;
while(qw[now+1].tim==qw[now].tim)++now;
rep(q,last,now) {
Max=-1e9,adv=qw[q].val,at=qw[q].at;
mid_add(1,len_max);
}
dep(q,now,last) {
Max=-1e9,adv=qw[q].val,at=qw[q].at;
add(1,len_max);
}
rep(q,last,now){
adv=md[qw[q].at];
at=qw[q].at;
replace(1,len_max);
}
++now;
}
int ans=0;
rep(q,1,len_max)ans=max(ans,val[q]-dis(q,st));
cout<<ans;
}
int main() {
// freopen("salesman.in","r",stdin);
// freopen("salesman.out","w",stdout);
in(n),in(n_cost),in(s_cost),in(st);
len_max=st;
rep(q,1,n)in(qw[q].tim),in(qw[q].at),in(qw[q].val),len_max=max(len_max,qw[q].at);
sort(qw+1,qw+n+1);
solve();
return 0;
}
「IOI2009」旅行商的更多相关文章
- 「SCOI2014」方伯伯的商场之旅 解题报告
「SCOI2014」方伯伯的商场之旅 我一开始的想法会被两个相同的集合位置去重给搞死,不过应该还是可以写的,讨论起来老麻烦. 可以先钦定在\(1\)号点集合,然后往后调整一部分. 具体一点,通过前缀和 ...
- 「SCOI2014」方伯伯的商场之旅
「SCOI2014」方伯伯的商场之旅 题目描述 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石 ...
- Bzoj3352 [ioi2009]旅行商
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 89 Solved: 36 Description 旅行商认定如何优化旅行路线是一个非常棘手的计算问题 ...
- Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题
一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...
- 一个「学渣」从零开始的Web前端自学之路
从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
随机推荐
- codevs 1300:文件排版(DP)
题目描述 写电子邮件是有趣的,但不幸的是经常写不好看,主要是因为所有的行不一样长,你的上司想要发排版精美的电子邮件,你的任务是为他编写一个电子邮件排版程序. 完成这个任务最简单的办法是在太短的行中的单 ...
- Chapter 20 Treatment-Confounder Feedback
目录 20.1 The elements of treatment-confounder feedback 20.2 The bias of traditional methods 20.3 Why ...
- [数学]高数部分-Part I 极限与连续
Part I 极限与连续 回到总目录 Part I 极限与连续 一.极限 泰勒公式 基本微分公式 常用等价无穷小 函数极限定义 数列极限数列极限 极限的性质 极限的唯一性 极限的局部有限性 极限的局部 ...
- 教你10分钟对接人大金仓EF Core 6.x
前言 目前.NET Core中据我了解到除了官方的EF Core外,还用的比较多的ORM框架(恕我孤陋寡闻哈,可能还有别的)有FreeSql.SqlSugar(排名不分先后).FreeSql和SqlS ...
- MySQL高级查询与编程笔记 • 【第1章 数据库设计原理与实战】
全部章节 >>>> 本章目录 1.1 数据需求分析 1.1.1 数据需求分析的定义 1.1.2 数据需求分析的步骤和方法 1.1.3 数据流程图 1.1.4 数据字典 1. ...
- Java高级程序设计笔记 • 【第5章 XML解析】
全部章节 >>>> 本章目录 5.1 XML 文档概述 5.1.1 XML文档结构 5.1.1 XML结构说明 5.1.1 XML文档元素 5.1.2 XML文档语法规范 ...
- pod内执行kill -3 pid
1.使用logs命令监控输出 kubectl logs iothub2-iop-dm-replicaset-0 -n iot -f >> yuanqianqian.txt 2.在p ...
- 『无为则无心』Python函数 — 30、Python变量的作用域
目录 1.作用于的概念 2.局部变量 3.全局变量 4.变量的查找 5.作用域中可变数据类型变量 6.多函数程序执行流程 1.作用于的概念 变量作用域指的是变量生效的范围,在Python中一共有两种作 ...
- 把rocksdb配置成leveldb
将rocksdb配置成leveldb 1.配置方法 配置方式有三种: 第一种适合进行性能测试对比:是以参数形式在运行db_bench或ycsb-c的时候以参数形式将rocksdb将其配置成leveld ...
- js 中&&的使用
遇到下列代码goHome && (await router.replace(PageEnum.BASE_HOME)); &&这个逻辑与的作用是,当goHome为true ...