「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 ...
随机推荐
- Interval Bound Propagation (IBP)
目录 概 主要内容 IBP CROWN CROWN-IBP 训练的技巧 写在最后 代码 Gowal S., Dvijotham K., Stanforth R., Bunel R., Qin C., ...
- Adaptive gradient descent without descent
目录 概 主要内容 算法1 AdGD 定理1 ADGD-L 算法2 定理2 算法3 ADGD-accel 算法4 Adaptive SGD 定理4 代码 Malitsky Y, Mishchenko ...
- Type-C扩展芯片|Type-C扩展方案|CSCapstone|扩展坞方案选型
一.关于Capstone Capstone科技于2018年8月在台湾成立.团队成员的多样性将硅谷和台湾的才华横溢的人联系在一起,以进行协作和取得优越成就. Capstone科技是由一个经验丰富的研发团 ...
- 论文翻译:2020_Acoustic Echo Cancellation by Combining Adaptive Digital Filter and Recurrent Neural Network
论文地址:https://arxiv.53yu.com/abs/2005.09237 自适应数字滤波与循环神经网络相结合的回声消除技术 摘要 回声消除(AEC)在语音交互中起关键作用.由于明确的数学原 ...
- Eclipse启动SpringCloud微服务集群的方法
1.说明 下面这篇文章介绍了Eureka Server集群的启动方法, SpringCloud创建Eureka模块集群 是通过jar包启动时指定配置文件的方式实现的. 现在只有Eureka Serve ...
- 数据库SQL语言类型(DQL.DML.DDL.DCL)
1.SQL语言 SQL(Structure Query Language)语言是数据库的核心语言. SQL是一个标准的数据库语言, 是面向集合的描述性非过程化语言. 它功能强,效率高,简单易学易维护. ...
- 记一次log4j2引发的渗透测试
前言 记一次log4j2打入内网并用CVE-2021-42287.CVE-2021-42278获取到DC权限的靶场渗透. 外网打点 首先对web进行端口扫描,发现38080端口和22端口 访问一下38 ...
- Linux中安装java JDK
Linux中安装java JDK 1.下载jdk 下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads. ...
- ffmpeg+nginx截取屏幕实时画面并进行rtmp推流在前端播放
准备环境和文件 1.下载ffmpeg的包[https://foxbaby.lanzoui.com/iYjPmup51cd] 地址:https://ffmpeg.org/download.html#bu ...
- day3 创建数组并完成对数组的操作
1.实现函数action()初始化数据全0的操作 2.实现函数assignment()利用指针给数组赋值0~9 3.实现函数print()打印数组的每个函数 4.实现函数reverse()完成对数组的 ...