IOI2014 day2 task4 Holiday
题目
大意:从左到右有\(n\)个城市,一开始在城市\(start\),每一天有两种选择:
- 前往相邻的城市。
- 访问当前城市(每个城市只能访问一次),访问城市\(i\)可以获得\(attraction_i\)的分数。
问:在\(d\)天内最多能获得多少分数。
算法
首先,分成左右两边来做,路线有\(4\)种:
- 往右走
- 往左左
- 现往右再往左
- 先往左再往右
将左右分开做,对于往右走,计算出\(f(i)\),表示往右走不回头在\(i\)内最大得分;以及\(g(i)\),表示往右走但是要回到原点在\(i\)天内的最大得分。计算答案时只需要根据上面所说的\(4\)种情况进行枚举\(d\)的分布(即枚举\(i\)天在城市\(start\)右边转,\(d-i\)天在左边转)就可以了。
这里讲讲如何计算\(f\),那计算\(g\)是类似的。
那如何计算\(f(i)\)呢?
枚举最远到达的城市\(j\),那么就有\(i-j\)天的时间去访问城市,那当然访问最大的\(i-j\)个城市啦。这个用线段树可以实现求城市\(start\)到城市\(j\)中,得分最大的前\(i-j\)的城市的和。这样求一次\(f(i)\)的复杂度是\(O(n \cdot logn)\)。
那如何求所有的\(f(i)\)呢,有一个神奇的东西:
设\(f'(i)\)为,求\(f(i)\)时,得到最大得分的枚举的那个城市\(j\)。那么对于$ i' < i \(,有\)f'(i') \leqslant f'(i)$。这样子,就可以分治了。
现在求\(f(1)\),\(f(2),... ,f(d)\)(\(d\)是最大天数),需要枚举的\(j\)为\(start,...,n\),设\(m= (1 + d) \text { div } 2\),用上述方法求出\(f(m)\)。然后递归求\(f(1),f(2),...,f(m-1)\),注意,此时枚举的\(j\)只是\(start,start+1,...,f'(m)\),范围缩小了。另外还要递归求\(f(m+1),f(m+2),...,f(n)\),此时枚举的\(j\)只是\(sf'(m),f'(m)+1,...,n\)。
所以,我们得到一个\(O(n\cdot log^2 n)\)的算法。
代码
写得不好。
#include"holiday.h"
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <assert.h>
using namespace std;
#ifdef debug
#define ep(...) fprintf(stderr, __VA_ARGS__)
#else
#define ep(...) assert(true)
#endif
typedef long long int i64;
const int MaxN = (int) 1e5 + 3;
const int MaxM = MaxN * 2 + MaxN / 2;
const int MaxT = 262144;
struct Node
{
i64 sum;
int cnt;
}T[MaxT];
#define idxl (idx << 1)
#define idxr (idx << 1 ^ 1)
void Modify(int idx, int L, int R, int x, int t, int val)
{
if (L == R)
{
T[idx].cnt = t;
T[idx].sum = t ? val : 0;
}
else
{
int M = (L + R) >> 1;
if (x <= M) Modify(idxl, L, M, x, t, val);
else Modify(idxr, M + 1, R, x, t, val);
T[idx].cnt = T[idxl].cnt + T[idxr].cnt;
T[idx].sum = T[idxl].sum + T[idxr].sum;
}
}
i64 Query(int idx, int k)
{
if (k >= T[idx].cnt) return T[idx].sum;
if (T[idxl].cnt >= k) return Query(idxl, k);
return T[idxl].sum + Query(idxr, k - T[idxl].cnt);
}
struct OneSide_struct
{
int n, m;
int A[MaxN];
pair<int, i64> f[MaxM], g[MaxM];
bool goback;
pair<int, int> tmp[MaxN];
int rank[MaxN];
void Init()
{
for (int i = 0; i < n; i ++)
tmp[i] = make_pair(A[i], i);
sort(tmp, tmp + n);
for (int i = 0; i < n; i ++)
rank[tmp[i].second] = n - i - 1;
}
pair<int, i64> Compute(int d, int x, int y)
{
pair<int, i64> ret = make_pair(-1, -1);
for (int i = x; i <= y; i ++)
{
Modify(1, 0, n - 1, rank[i], 1, A[i]);
int rest = d - (goback ? i << 1 : i);
if (rest <= 0) break;
i64 tmp = Query(1, rest);
if (tmp > ret.second)
{
ret.first = i;
ret.second = tmp;
}
}
for (int i = x; i <= y; i ++)
Modify(1, 0, n - 1, rank[i], 0, A[i]);
assert(ret.second != -1);
return ret;
}
void Solve(int L, int R, int x, int y, pair<int, i64> ans[])
{
int M = (L + R) >> 1;
ans[M] = Compute(M, x, y);
if (L < M)
Solve(L, M - 1, x, ans[M].first, ans);
if (R > M)
{
for (int i = x; i < ans[M].first; i ++) Modify(1, 0, n - 1, rank[i], 1, A[i]);
Solve(M + 1, R, ans[M].first, y, ans);
}
for (int i = x; i < y; i ++) Modify(1, 0, n - 1, rank[i], 1, A[i]);
}
};
long long int findMaxAttraction(int n, int start, int m, int A[])
{
static OneSide_struct R, L;
R.n = 0;
for (int i = start; i < n; i ++)
R.A[R.n ++] = A[i];
R.m = m;
R.Init();
R.goback = false;
R.Solve(1, R.m, 0, R.n - 1, R.f);
R.goback = true;
memset(T, 0, sizeof(T));
R.Solve(1, R.m, 0, R.n - 1, R.g);
L.n = 0;
for (int i = start - 1; i >= 0; i --)
L.A[L.n ++] = A[i];
L.m = m;
L.Init();
if (L.n)
{
L.goback = false;
memset(T, 0, sizeof(T));
L.Solve(1, L.m, 0, L.n - 1, L.f);
L.goback = true;
memset(T, 0, sizeof(T));
L.Solve(1, L.m, 0, L.n - 1, L.g);
}
#ifdef debug
for (int i = 0; i < m; i ++)
ep("R %d %lld %lld\n", i, R.f[i].second, R.g[i].second);
ep("\n");
for (int i = 0; i < m; i ++)
ep("L %d %lld %lld\n", i, L.f[i].second, L.g[i].second);
#endif
i64 ans = max(R.f[m].second, L.f[m - 1].second);
for (int i = 0; i < m; i ++)
ans = max(ans, R.g[i].second + L.f[m - i - 1].second);
for (int i = 0; i < m - 2; i ++)
ans = max(ans, L.g[i].second + R.f[m - i - 2].second);
return ans;
}
IOI2014 day2 task4 Holiday的更多相关文章
- WC2015 滚粗记
Day 0 和南师附中诸人去杭州,想到这是第三次去杭州有点感动 想到noi还要在杭州,简直…… 火车站接送好评如潮 ym大学军,到学军领资料然后到浙大宿舍安顿,noi的书包还是挺不错的 看起来宿舍还可 ...
- 【BZOJ4367】[IOI2014]holiday假期 分治+主席树
[BZOJ4367][IOI2014]holiday假期 Description 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市, ...
- [BZOJ4367][IOI2014]Holiday(决策单调性+分治+主席树)
4367: [IOI2014]holiday假期 Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 421 Solved: 128[Submit][Sta ...
- uoj#29. 【IOI2014】Holiday
http://uoj.ac/problem/29 经过的点集一定是一个包含start的区间,为了经过这个区间内所有点,必须先到达一个区间端点,再到达另一个区间端点,剩余的步数则贪心选区间内最大价值的点 ...
- luogu P5892 [IOI2014]holiday 假期 决策单调性优化dp 主席树
LINK:holiday 考虑第一个subtask. 容易想到n^2暴力枚举之后再暴力计算答案. 第二个subtask 暴力枚举终点可以利用主席树快速统计答案. 第三个subtask 暴力枚举两端利用 ...
- BZOJ4367 : [IOI2014]holiday假期
设 $fl[i]$表示从$S$向左走,用了不超过$i$天且不回头的最大收益. $fr[i]$表示从$S$向右走,用了不超过$i$天且不回头的最大收益. $gl[i]$表示从$S$向左走,用了不超过$i ...
- [IOI2014]holiday假期(分治+主席树)
题目描述 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市,它们全部位于一条高速公路上.这些城市连续地编号为0到n-1.对于城市i( ...
- BZOJ 4367 [IOI2014]holiday (决策单调DP+主席树+分治)
题目大意:略 题目传送门 神题,不写长题解简直是浪费了这道题 贪心 考虑从0节点出发的情况,显然一直往前走不回头才是最优策略 如果起点是在中间某个节点$s$,容易想到,如果既要游览$s$左边的某些景点 ...
- 【从零开始学BPM,Day2】默认表单开发
[课程主题]主题:5天,一起从零开始学习BPM[课程形式]1.为期5天的短任务学习2.每天观看一个视频,视频学习时间自由安排. [第二天课程] Step 1 软件下载:H3 BPM10.0全开放免费下 ...
随机推荐
- Cannot mix incompatible Qt library (version 0x40801) with this library (version 0x40804)
安装EMAN2(单颗粒重构的软件)之后,运行e2projectmanager.py来启动程序出现了这个错误. 去网上找了一下,发现一个靠谱的方案,这个问题出现是由于EMAN2这个程序自带了Qt的库,而 ...
- BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐( LIS )
求LIS , 然后用 n 减去即为answer ---------------------------------------------------------------------------- ...
- 服务器忘记mysql密码怎么修改?
找到配置文件my.ini ,然后将其打开,可以选择用记事本打开 打开后,搜索mysqld关键字 找到后,在mysqld下面添加skip-grant-tables,保存退出. PS:若提示不让保存时, ...
- 用jmeter进行多用户并发压力测试 [转]
近日manager要求对项目进行压力测试,开始对jmeter进行了研究.jmeter是Apache一个开源项目,可对各种项目进行测试,甚至包括junit. 测试要求如下,多用户同时登陆web应用程序, ...
- python笔记之字符串
列表,元组,字符串的相互转换: 将字符串转换为序列和元组: >>> s="hello" >>> list(s)['h', 'e', 'l', ' ...
- javascript 检测密码强度
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- lua学习:使用Lua处理游戏数据
在之前lua学习:lua作配置文件里,我们学会了用lua作配置文件. 其实lua在游戏开发中可以作为一个强大的保存.载入游戏数据的工具. 1.载入游戏数据 比如说,现在我有一份表单: data.xls ...
- 安装ubuntu时的注意事项----个人小总结
今天重装了一次ubuntu,以前是别人帮我装的,而这次是我自己照着网上教程装的. 这个教程还是挺不错的,我就是照着这个装成功的 http://jingyan.baidu.com/article/60c ...
- BZOJ 1601 [Usaco2008 Oct]灌水
1601: [Usaco2008 Oct]灌水 Time Limit: 5 Sec Memory Limit: 162 MB Description Farmer John已经决定把水灌到他的n(1 ...
- 1297 - Largest Box(三分)
1297 - Largest Box PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB In t ...