显然最优策略是先走到一边要到达的最远城市,再换方向走到另一边要到达的最远城市(当然也可以直接停止),路上参观景点。

  先仅考虑求出只向左走,花费时间i时的最优解。如果能求出这个,类似的就可以求出所有情况。

  显然时间越长,应该往左边走的越远,参观的越多,但是这个最远城市的变化不一定连续,没法愉快地双指针或者直接二分答案。

  考虑类似整体二分的做法。设当前要求i在l~r,最远城市在x~y之间的最优解,对i=mid暴力求出最优解,然后递归处理两边。暴力需要进行nlog次,每次暴力需要求区间k大和,可以用主席树做到log,于是复杂度O(nlog2n)。

  注意起点处只能取一次。并且对mid求出的最远点如果有多解考虑清楚选哪一个。

  upd:才想起来这玩意就是决策单调性

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
#define ll long long
int n,start,m,a[N],b[N],root[N],cnt,t;
ll fl[N<<],gl[N<<],fr[N<<],gr[N<<];
struct data{int l,r,x;ll sum;
}tree[N*];
struct data2{ll x;int d;};
void ins(int &k,int l,int r,int x)
{
tree[++cnt]=tree[k],k=cnt;
tree[k].x++,tree[k].sum+=b[x];
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,l,mid,x);
else ins(tree[k].r,mid+,r,x);
}
ll query(int x,int y,int l,int r,int k)
{
if (!y) return ;
if (l==r) return 1ll*min(tree[y].x-tree[x].x,k)*b[l];
int mid=l+r>>,t=tree[tree[y].r].x-tree[tree[x].r].x;
if (t>=k) return query(tree[x].r,tree[y].r,mid+,r,k);
else return tree[tree[y].r].sum-tree[tree[x].r].sum+query(tree[x].l,tree[y].l,l,mid,k-t);
}
data2 calc(int tot,int x,int y,int op,int isr)
{
int mx=isr?x:y;ll ans=;
if (isr)
{
for (int i=x;i<=y;i++)
if (tot>=abs(start-i)*(+op))
{
ll v;
if (i<start) v=query(root[i-],root[start-op],,t,tot-(start-i)*(+op));
else v=query(root[start-+op],root[i],,t,tot-(i-start)*(+op));
if (v>ans) ans=v,mx=i;
}
}
else
{
for (int i=y;i>=x;i--)
if (tot>=abs(start-i)*(+op))
{
ll v;
if (i<start) v=query(root[i-],root[start-op],,t,tot-(start-i)*(+op));
else v=query(root[start-+op],root[i],,t,tot-(i-start)*(+op));
if (v>ans) ans=v,mx=i;
}
}
return (data2){ans,mx};
}
void solve1(int l,int r,int x,int y)
{
if (l>r||x>y) return;
int mid=l+r>>;data2 t=calc(mid,x,y,,);
fl[mid]=t.x;
solve1(l,mid-,t.d,y);
solve1(mid+,r,x,t.d);
}
void solve2(int l,int r,int x,int y)
{
if (l>r||x>y) return;
int mid=l+r>>;data2 t=calc(mid,x,y,,);
fr[mid]=t.x;
solve2(l,mid-,x,t.d);
solve2(mid+,r,t.d,y);
}
void solve3(int l,int r,int x,int y)
{
if (l>r||x>y) return;
int mid=l+r>>;data2 t=calc(mid,x,y,,);
gl[mid]=t.x;
solve3(l,mid-,t.d,y);
solve3(mid+,r,x,t.d);
}
void solve4(int l,int r,int x,int y)
{
if (l>r||x>y) return;
int mid=l+r>>;data2 t=calc(mid,x,y,,);
gr[mid]=t.x;
solve4(l,mid-,x,t.d);
solve4(mid+,r,t.d,y);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4367.in","r",stdin);
freopen("bzoj4367.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),start=read()+,m=read();
for (int i=;i<=n;i++) b[i]=a[i]=read();
sort(b+,b+n+);
t=unique(b+,b+n+)-b-;
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b+t+,a[i])-b;
for (int i=;i<=n;i++)
{
root[i]=root[i-];
ins(root[i],,t,a[i]);
}
solve1(,m,,start);
solve2(,m,start,n);
solve3(,m,,start-);
solve4(,m,start+,n);
ll ans=;
for (int i=;i<=m;i++)
ans=max(ans,gl[i]+fr[m-i]),
ans=max(ans,gr[i]+fl[m-i]);
cout<<ans;
return ;
}

BZOJ4367 IOI2014holiday假期(整体二分+主席树)的更多相关文章

  1. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  2. 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】

    题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...

  3. BZOJ3110 K大数查询 【线段树 + 整体二分 或 树套树(非正解)】

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  4. 【BZOJ 4556】[Tjoi2016&Heoi2016]字符串 SAM+二分+主席树

    这道题市面上就两种法:一种是SA+二分+主席树,一种是SAM+二分+主席树(有不少人打线段树合并???)(除此之外还有一种利用炒鸡水的数据的暴力SA,贼快.....)(当时学SA的时候没做这道题,现在 ...

  5. 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

    [BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...

  6. BZOJ2653 middle 【二分 + 主席树】

    题目 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c ...

  7. BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

    整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...

  8. bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...

  9. [bzoj2653][middle] (二分 + 主席树)

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

随机推荐

  1. Linux入门-第五周

    1.磁盘lvm管理,完成下面要求,并写出详细过程: 1) 创建一个至少有两个PV组成的大小为20G的名为testvg的VG;要求PE大小 为16MB, 而后在卷组中创建大小为5G的逻辑卷testlv; ...

  2. struts2的token interceptor

    关于struts2的token拦截器的说明 原理:struts2的token interceptor是关于重复提交的拦截器,其实现是:在form表单中加入token标签,如下: <form ac ...

  3. 高级同步器:信号量Semaphore

    引自:https://blog.csdn.net/Dason_yu/article/details/79734425 一.信号量一个计数信号量.从概念上讲,信号量维护了一个许可集.Semaphore经 ...

  4. MySQL必会

    SQL语言对大小写不敏感,但一般使用大.1.创建数据库 CREATE DATABASE test; 2.授予权限 CRANT ALL ON test.* to user(s); 3.使用指定数据库 U ...

  5. python-生成器单线程并发(简单案例)

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- import time # ----------示例---------- def consumer(na ...

  6. 2019-04-10 python入门学习——教材和工具准备

    # 从决定学习编程语言到正式做出计划挤出空余时间,历经一年半,因工作原因及生活原因不断搁浅,从湖北到浙江再回湖北,暂时稳定在一家小公司,从日常加班中压缩时间学习,于此记录学习进度.学习问题,在此过程中 ...

  7. ABAP CDS ON HANA-(10)項目結合して一つ項目として表示

    Numeric Functions ABS(arg)  CEIL(arg) DIV(arg1, arg2) DIVISION(arg1, arg2, dec) FLOOR(arg) MOD(arg1, ...

  8. .Net 面试题 汇总(三)

    101.ASP.net的身份验证方式有哪些?分别是什么原理? 答:Windwos(默认)用IIS... From(窗体)用帐户 Passport(密钥) 102.在.net中,配件的意思是? 答:程序 ...

  9. Sqoop的安装配置及使用

    一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据移植过去并不容易.Apache Sqoop正在加 ...

  10. Ubuntu无法安装vim怎么办?(Ubuntu 出现apt-get: Package has no installation candidate问题)

    apt-get install vim 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 有一些软件包无法被安装.如果您用的是不稳定(unstable)发行版, ...