Description

有\(N(N\leq 10^5)\)个排列在一条线上的城市,每个城市有\(val_i\)个景点。每天你可以选择在当前城市\(i\)游览景点,或者前往城市\(i-1\)或城市\(i+1\)。给定起点和天数,请最大化游览的景点。一个城市的景点最多只会被游览一次。

Solution

1A IOI真是劲啊

因为这个游览城市没有“过期”一说,所以我们没必要蛇形走位,也就是说,我们行进的路线只有四种情况:一直向右,一直向左,先向左再向右,先向右再向左。这样可以求出来四个数组。

以求一直向右为例,设\(f[i]\)表示一直向右走\(i\)天的最大收益。观察到决策点是单调的,我们可以分治\(solve(l,r,x,y)\)表示要求\(f[l...r]\),决策点在\([x,y]\)。具体求法可以用主席树查前\(K\)大的值来实现。

其他三个求法也是类似的。还要注意一点就是我们强制让后两种情况的\(f[i]\)表示经过\(i\)天又回到起点的最大收益,然后用回到起点的最大收益加上从起点出发的最大收益更新答案就行了。

Code

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using std::min;
using std::max;
using std::swap;
using std::vector;
const int N=1e5+5;
const int M=N*3;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define mp(A,B) std::make_pair(A,B)
#define ls ch[cur][0]
#define rs ch[cur][1] ll a[5][M];
int n,s,m,len,tot,val[N],g[N];
int root[N],ch[N*20][2];ll sum[N*20][2]; int getint(){
int X=0,w=0;char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} int modify(int pre,int l,int r,int c){
int cur=++tot;
sum[cur][1]=sum[pre][1]+g[c];sum[cur][0]=sum[pre][0]+1;ls=ch[pre][0];rs=ch[pre][1];
if(l==r) return cur;
int mid=l+r>>1;
if(c<=mid) ls=modify(ch[pre][0],l,mid,c);
else rs=modify(ch[pre][1],mid+1,r,c);
return cur;
} ll query(int pre,int cur,int l,int r,int k){
if(sum[cur][0]-sum[pre][0]<=k) return sum[cur][1]-sum[pre][1];
if(l==r) return (ll)g[l]*k;
int mid=l+r>>1;
if(sum[rs][0]-sum[ch[pre][1]][0]>k) return query(ch[pre][1],ch[cur][1],mid+1,r,k);
return sum[rs][1]-sum[ch[pre][1]][1]+query(ch[pre][0],ls,l,mid,k-sum[rs][0]+sum[ch[pre][1]][0]);
} int abs(int x){
return x<0?-x:x;
} void solve(int l,int r,int x,int y,int pd){
if(l>r) return;
int mid=l+r>>1,idx=0;//一共走mid天
for(int i=x;i<=y;i++){
ll t;
if(pd==1) t=query(root[s-1],root[i],1,len,mid-abs(i-s));
else if(pd==2) t=query(root[i-1],root[s-1],1,len,mid-abs(i-s));
else if(pd==3) t=query(root[s-1],root[i],1,len,mid-abs(i-s)*2);
else t=query(root[i-1],root[s-1],1,len,mid-abs(i-s)*2);
if(t>a[pd][mid]) a[pd][mid]=t,idx=i;
}
if(pd==1 or pd==3) solve(l,mid-1,x,idx,pd),solve(mid+1,r,idx,y,pd);
else solve(l,mid-1,idx,y,pd),solve(mid+1,r,x,idx,pd);
} signed main(){
n=getint(),s=getint()+1,m=getint();
for(int i=1;i<=n;i++)g[i]=val[i]=getint();
std::sort(g+1,g+1+n);len=std::unique(g+1,g+1+n)-g-1;
for(int i=1;i<=n;i++){
val[i]=std::lower_bound(g+1,g+1+len,val[i])-g;
root[i]=modify(root[i-1],1,len,val[i]);
}
solve(1,m,s,n,1);solve(1,m,1,s,2);
solve(1,m,s,n,3);solve(1,m,1,s,4);
for(int i=1;i<=m;i++)
for(int j=1;j<=4;j++)
a[j][i]=max(a[j][i],a[j][i-1]);
ll ans=max(a[1][m],a[2][m]);
for(int i=1;i<m;i++)
ans=max(ans,max(a[3][i]+a[2][m-i],a[4][i]+a[1][m-i]));
printf("%lld\n",ans);
return 0;
}

[IOI2014] 假期的更多相关文章

  1. 【BZOJ4367】[IOI2014]holiday假期 分治+主席树

    [BZOJ4367][IOI2014]holiday假期 Description 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市, ...

  2. [IOI2014]holiday假期(分治+主席树)

    题目描述 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市,它们全部位于一条高速公路上.这些城市连续地编号为0到n-1.对于城市i( ...

  3. BZOJ4367 : [IOI2014]holiday假期

    设 $fl[i]$表示从$S$向左走,用了不超过$i$天且不回头的最大收益. $fr[i]$表示从$S$向右走,用了不超过$i$天且不回头的最大收益. $gl[i]$表示从$S$向左走,用了不超过$i ...

  4. luogu P5892 [IOI2014]holiday 假期 决策单调性优化dp 主席树

    LINK:holiday 考虑第一个subtask. 容易想到n^2暴力枚举之后再暴力计算答案. 第二个subtask 暴力枚举终点可以利用主席树快速统计答案. 第三个subtask 暴力枚举两端利用 ...

  5. [BZOJ4367][IOI2014]Holiday(决策单调性+分治+主席树)

    4367: [IOI2014]holiday假期 Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 421  Solved: 128[Submit][Sta ...

  6. BZOJ1433 ZJOI2009 假期的宿舍 二分图匹配

    1433: [ZJOI2009]假期的宿舍 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2375  Solved: 1005[Submit][Sta ...

  7. 假期实践作业:从IT角度看地铁

    实习时间:2016/02/23——2016/02/26 实习地点:京港地铁14号线 实习报告: 大学四年过得真快,转眼就大三了,大学前两年半的生活可谓多姿多彩,从不懂计算机到对编程感兴趣,期待得最多的 ...

  8. 2055 [ZJOI2009]假期的宿舍

    P2055 [ZJOI2009]假期的宿舍 题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A ...

  9. 假期(codevs 3622)

    题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择一段(需要连续),每一天都有一个享受指数W.但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不 ...

随机推荐

  1. .net 资源释放(托管资源和非托管资源)

    1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...

  2. 【轻松前端之旅】<a>元素妙用

    浏览器读取服务器内容时,通过URL(包含:协议+域名+绝对路径)如:https://www.baidu.com/index.html浏览器从本地读取内容时,会用file协议.如:file:///E:/ ...

  3. Android 简单布局、控件

    布局 线性布局 LinearLayout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android ...

  4. 在linux中文件的权限讲解

    1.d:directory(目录): 表示这个文件是个目录,其他的还有f(file文件)等等: 2.r:read(可读) 3.w:write(可写) 4 x :execute(可执行) 一般Linux ...

  5. Clion pycharm激活码(可使用到2019年2月)

    D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...

  6. C/C++ 的宏中#和##的作用和展开

    C/C++ 的宏中: (1) # 的功能是将其后面的宏参数进行字符串化操作,简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号. 也就是说: #define __TO_STRING_IM ...

  7. Python学习第四章

    1.类和对象: 类对象支持两种操作:属性引用和实例化. 属性引用:obj.name 构造方法:类会定义一个名为__int__()的特殊方法如下 def  __init__(self):       s ...

  8. day_2安装Python解释器和pycharm

    首先我们复习一下昨天的内容 ···重点 1:进制转换:二进制 与 十六进制 1111  0101 1010 转换为 f5a 2:内存分布:堆区 和 栈区 计算机的原理: 控制器 运算器 存储器 inp ...

  9. 使用Docker搭建CentOS 7 + Apache 2.4+ PHP7

    从Docker Hub上Pull最新的CentOS 7镜像并新建容器 # sudo docker pull centos docker run -p 8082:80 --name centos_c - ...

  10. Android开发工程师文集-1 小时学会Widget小组件开发

    前言 大家好,给大家带来Android开发工程师文集-1 小时学会Widget小组件开发的概述,希望你们喜欢 学会用Widget (小组件) Widget小组件很方便,很快捷,可以个性化,自己定制,相 ...