博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[IOI2014] 假期
阅读量:5214 次
发布时间:2019-06-14

本文共 2806 字,大约阅读时间需要 9 分钟。

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#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

转载于:https://www.cnblogs.com/YoungNeal/p/9807471.html

你可能感兴趣的文章
PHPExcel正确读取excel表格时间单元格(转载)
查看>>
统计学习方法十:隐马尔科夫模型二
查看>>
[Ruby on Rails] Concepts
查看>>
解决flask局域网内访问不了的问题
查看>>
linux命令后台运行详解
查看>>
Python 用Redis简单实现分布式爬虫
查看>>
task_struct
查看>>
linux 命令
查看>>
【BZOJ】【1022】【SHOI2008】小约翰的游戏John
查看>>
web.xml配置详解
查看>>
hdu2044一只小蜜蜂
查看>>
js,css三种方法解决IE6下position:fixed的Bug以及闪动问题
查看>>
Project Server and Project Professional – Getting them to communicate!
查看>>
Linux 下网路适配器配置
查看>>
<Android基础> (七)内容提供器
查看>>
创建一个dynamics 365 CRM online plugin (七) - plugin当中的Impersonation角色
查看>>
Linux - Linux系统目录架构
查看>>
POJ 3378 (大整数加法+树状数组)
查看>>
树莓派下安装windows10IoT系统以及opencv安装
查看>>
NOIP2004【虫食算】(DFS)
查看>>