LINK:holiday

考虑第一个subtask.

容易想到n^2暴力枚举之后再暴力计算答案.

第二个subtask 暴力枚举终点可以利用主席树快速统计答案.

第三个subtask 暴力枚举两端利用主席树计算贡献。

最后一个 subtask.

容易想到还是固定左端点来不断的寻找右端点。

不过很遗憾这最多只能做到\(n^2logn\)

需要从其他的角度入手 感觉前面几个subtask一直在迷惑选手。

可以从天数下手 左边多少天右边多少天。

显然 需要预处理出\(f1_i,f2_i\)分别表示从起点向右走i天能获得的最大价值,向右并且回到起点的最大价值.

左边同理.

答案利用这两个数字进行拼接即可。

值得注意的是 起点只能分给左右两边的一个并判断好边界问题。

然后就是求f数组了 容易想到枚举决策+贡献。

可以发现这是具有决策单调性的。证明不需要四边形不等式 下面我口胡一个。

假设有\(i,j,p\)其中\(p\)是\(j\)的最优决策 且\(i<j\) 那么对于i的最优决策一定\(<=p\)

反证法:若i的最优决策\(k>p\) 那么\(j\)也可以用\(k\)这个决策 i可以用\(p\)这个决策 把i在p这个决策时候用到的点和 在k用到的点标记。

可以发现k用到的点的和大于i用到的点的和 j也用k的话 由于j在p是包含i在p的选择 所以j也可以变成i \(p->k\)的样子 且其他东西不变 可以发现这样会更优。

所以j的最优决策会是k而不是p 与原命题相悖 所以假设成立。

总复杂度\(n\cdot log^2n\)

code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 10000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-4
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define V vector<int>
#define l(x) t[x].l
#define r(x) t[x].r
#define sum(x) t[x].sum
#define cnt(x) t[x].cnt
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=100010,maxn=300010;
int n,m,s1,op,ans,top,id;
int a[MAXN],b[MAXN],root[MAXN];
ll sum[MAXN];
ll f1[maxn];//从原点出发向右走的最大值.
ll f2[maxn];//从原点出发向右走之后走回起点的最大值.
ll f3[maxn];//从原点出发向左走的最大值.
ll f4[maxn];//从原点出发向左走之后走回起点的最大值.
struct wy
{
int l,r;
ll sum;
int cnt;
}t[MAXN*20];
inline void discrete()
{
sort(a+1,a+1+n);
rep(1,n,i)if(i==1||a[i]!=a[i-1])a[++top]=a[i];
rep(1,n,i)b[i]=lower_bound(a+1,a+1+top,b[i])-a;
}
inline void insert(int las,int &p,int l,int r,int x)
{
p=++id;t[p]=t[las];
sum(p)+=a[x];++cnt(p);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)insert(l(las),l(p),l,mid,x);
else insert(r(las),r(p),mid+1,r,x);
}
inline ll ask(int x,int y,int l,int r,int k)
{
if(l==r)return (ll)k*a[l];
int mid=(l+r)>>1;
if(cnt(r(x))-cnt(r(y))>=k)return ask(r(x),r(y),mid+1,r,k);
return ask(l(x),l(y),l,mid,k-cnt(r(x))+cnt(r(y)))+sum(r(x))-sum(r(y));
}
inline ll ask(int l,int r,int k)
{
//求区间l~r的前k大的和.
ans=0;
if(k>=r-l+1)return sum[r]-sum[l-1];
return ask(root[r],root[l-1],1,top,k);
}
inline void solve1(int l,int r,int L,int R)
{
int mid=(l+r)>>1;int p=L,res;
rep(L,R,j)
{
res=mid-op*(j-s1);
if(res<=0)continue;
ll cc=ask(s1,j,res);
if(cc>f1[mid])
{
f1[mid]=cc;
p=j;
}
}
if(l<mid)solve1(l,mid-1,L,p);
if(r>mid)solve1(mid+1,r,p,R);
}
inline void solve2(int l,int r,int L,int R)
{
int mid=(l+r)>>1;int p=L,res;
rep(L,R,j)
{
res=mid-op*(j-s1);
if(res<=0)continue;
ll cc=ask(s1,j,res);
if(cc>f2[mid])
{
f2[mid]=cc;
p=j;
}
}
if(l<mid)solve2(l,mid-1,L,p);
if(r>mid)solve2(mid+1,r,p,R);
}
inline void solve3(int l,int r,int L,int R)
{
int mid=(l+r)>>1;int p=L,res;
fep(L,R,j)
{
res=mid-op*(s1-j);
if(res<=0)continue;
ll cc=ask(j,s1-1,res);
if(cc>f3[mid])
{
f3[mid]=cc;
p=j;
}
}
if(l<mid)solve3(l,mid-1,L,p);
if(r>mid)solve3(mid+1,r,p,R);
}
inline void solve4(int l,int r,int L,int R)
{
int mid=(l+r)>>1;int p=L,res;
fep(L,R,j)
{
res=mid-op*(s1-j);
if(res<=0)continue;
ll cc=ask(j,s1-1,res);
if(cc>f4[mid])
{
f4[mid]=cc;
p=j;
}
}
if(l<mid)solve4(l,mid-1,L,p);
if(r>mid)solve4(mid+1,r,p,R);
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(s1)+1;get(m);
rep(1,n,i)b[i]=get(a[i]),sum[i]=sum[i-1]+a[i];
discrete();
rep(1,n,i)insert(root[i-1],root[i],1,top,b[i]);
op=1;solve1(1,m,s1,n);//规定右边带起点.
op=2;solve2(1,m,s1,n);
op=1;if(s1-1>=1)solve3(1,m,s1-1,1);
op=2;if(s1-1>=1)solve4(1,m,s1-1,1);
ll ans=0;rep(0,m,i)ans=max(ans,max(f1[i]+f4[m-i],f2[i]+f3[m-i]));
putl(ans);return 0;
}

luogu P5892 [IOI2014]holiday 假期 决策单调性优化dp 主席树的更多相关文章

  1. 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)

    题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...

  2. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  3. CF868F Yet Another Minimization Problem 分治决策单调性优化DP

    题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...

  4. 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)

    传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...

  5. [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)

    第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...

  6. BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】

    Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt( ...

  7. 决策单调性优化dp 专题练习

    决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...

  8. 算法学习——决策单调性优化DP

    update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...

  9. BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】

    Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...

随机推荐

  1. 脱壳实践之寻找OEP——两次内存断点法

      0x00 前言 对于加壳程序第一件事就是要找到OEP(oringinal Entry point),由于加壳的缘故,当PE文件载入OD或者其他调试软件时进入的的往往是壳程序的入口地址.所以要进行逆 ...

  2. Redis的持久化——RDB和AOF

    推荐阅读 Redis 持久化之RDB和AOF --来自ITDragon龙 Redis Persistence --来自Redis官网文档

  3. input函数报错"*** is not defined"

    #键盘输入输出name = input('input your name: ') print("姓名:"+name) 运行结果: 只需要在输入时加引号,如"yu" ...

  4. day11总结

    """1.什么是函数 具备某一功能的工具===>函数 事先准备工具的过程===>函数的定义 遇到应用场景拿来就用=>函数的调用 2.为何要有函数 内置函 ...

  5. DVWA学习记录 PartⅡ

    Command Injection 1. 题目 Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的. 2. Low a. 代码分析 ...

  6. 概率图模型(CPD)(二)

    CPD是conditional probability distribution的缩写,翻译成中文叫做 条件概率分布.在概率图中,条件概率分布是一个非常重要的概念.因为概率图研究的是随机变量之间的练习 ...

  7. nginx反向代理导致session失效的问题处理

    一同事求援:后台系统的登录成功了,但不能成功登进系统,仍然跳转到登录页,但同一套代码另一个环境却没有问题. 背景 经了解,他对同一个项目使用tomcat部署了两个环境,一个在开发服务器上,一个在他本机 ...

  8. day4:运算符

    1.算术运算符:+ - * / // % ** 注意点:1./ 除法,结果为小数  2.// 地板除,返回整数  3.如果被除数或者除数是一个小数,结果加上.0 2.比较运算符:< > & ...

  9. 【高性能Mysql 】读书笔记(一)

    第1章 Mysql架构与历史 MYSQL最重要.最与众不同的特性是它的存储引擎架构,这种架构的设计将查询处理( Query Processing)及其他系统任务( Server Task)和数据的存储 ...

  10. db2数据库基本添加删除表字段总结

    1.添加字段 alter table [table_name] add [column_name] [column_type] 2.更改字段类型 alter table  [table_name] a ...