题解 「BZOJ3636」教义问答手册
Description
作为泉岭精神的缔造者、信奉者、捍卫者、传承者,Pear决定印制一些教义问答手册,以满足泉岭精神日益增多的信徒。Pear收集了一些有关的诗选、语录,其中部分内容摘录在了【题目背景】里。这些语录是按出现的时间排好序的——Pear很喜欢这样的作风,于是决定在按时间排好序的基础上,选择部分语录,制作成若干本教义问答手册。
一共有N条语录。Pear决定从中选出某一段时间内的所有语录,在此基础上印制大小为L的若干本教义问答手册。Pear对印制的手册有如下要求:
1. 每本手册必须包含这个区间内连续的恰好L条语录。
2. 不同手册包含的语录不能相同。
3. 每条语录有一个“主题相关程度”,这个数可正可负。Pear希望所有手册的语录的“主题相关程度”之和尽可能大。
例如,对于区间[3,15]和L=3,一种选择方法是:[4,6]+[9,11]+[12,14]。这三个区间长度都恰好为L,且互不重叠。
Pear并没有决定选哪段时间的语录,因此他有Q次询问。每次询问,给出两个数[l,r]表示候选语录的范围是第l条到第r条。你能回答出每个询问的最大“主题相关程度”之和么?
\(n,q\le 10^5,L\le 50\)
Solution
这个题在有了提示(知道是分治)之后竟然自己做出来了,这里写一发记录一下。
考虑单次询问怎么做,可以想到,我们可以设 \(f_i\) 表示前面 \(i\) 个数产生的最大贡献,那么我们可以得到转移式:
\]
其中 \(h_{0,1,2,3,...,n}\) 是前缀和。答案就是 \(f_r\)。
考虑优化。因为这个题长度是固定的,所以我们就可以考虑整体操作。
假设我们现在在操作 \([l,r]\),那么,我们现在能更新的答案就是左右端点在 \(mid\) 两侧的,其它的可以继续递归下去。
可以想到的是,在中点两侧的询问一定是要么中间不选要么就是中间选一个(跨界的)区间。因为这个区间长度很小,所以我们就可以预处理出 \(f1_{st,i},f2_{st,i}\) 分别表示从前往后(从后往前)起点在 \(st\),到 \(i\) 这一段产生的贡献,然后枚举一下如果中间选了一个区间的话左边选了多少个以及不选的情况。
复杂度就是 \(\Theta(n\log nL)\),但是因为跑不满所以还是很快的。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define int long long
#define MAXN 100005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,q,len,pre[MAXN],ans[MAXN];
struct node{
int ind,qL,qR;
};
typedef vector<node> poly;
#define SZ(A) ((int)A.size())
#define MAXL 55
int f1[MAXL][MAXN],f2[MAXL][MAXN];
void doit1 (int l,int r){//从左往右
for (Int st = 0;st <= len;++ st){
int s = l + st;f1[st][s - 1] = 0;
for (Int i = l;i <= r;++ i)
if (i < s) f1[st][i] = 0;
else{
f1[st][i] = f1[st][i - 1];
if (i - len + 1 >= s) f1[st][i] = max (f1[st][i],f1[st][i - len] + pre[i] - pre[i - len]);
}
}
}
void doit2 (int l,int r){
for (Int st = 0;st <= len;++ st){
int s = r - st;f2[st][s + 1] = 0;
for (Int i = r;i >= l;-- i)
if (i > s) f2[st][i] = 0;
else{
f2[st][i] = f2[st][i + 1];
if (i + len - 1 <= s) f2[st][i] = max (f2[st][i],f2[st][i + len] + pre[i + len - 1] - pre[i - 1]);
}
}
}
void chkmx (int &a,int b){a = max (a,b);}
void cdq (int l,int r,poly S){
if (l > r || !SZ(S)) return ;
int mid = (l + r) >> 1;doit1 (mid,r),doit2 (l,mid);
poly S1,S2;S1.clear (),S2.clear ();
for (Int i = 0;i < SZ(S);++ i){
if (S[i].qL <= mid && S[i].qR >= mid){
chkmx (ans[S[i].ind],f1[1][S[i].qR] + f2[0][S[i].qL]);
for (Int st = 1;st <= len && mid - st + len <= n && mid - st >= 0;++ st)
if (S[i].qR >= mid + st - 1 && S[i].qL <= mid - (len - st + 1) + 1)
chkmx (ans[S[i].ind],f1[st][S[i].qR] + max (0ll,pre[mid + st - 1] - pre[mid - (len - st + 1)]) + f2[len - st + 1][S[i].qL]);
}
else if (S[i].qR <= mid) S1.push_back (S[i]);
else S2.push_back (S[i]);
}
cdq (l,mid,S1),cdq (mid + 1,r,S2);
}
signed main(){
read (n,len);
for (Int i = 1,x;i <= n;++ i) read (x),pre[i] = pre[i - 1] + x;
read (q);poly S;for (Int i = 1;i <= q;++ i){
int l,r;read (l,r);
S.push_back (node {i,l,r});
}
cdq (1,n,S);
for (Int i = 1;i <= q;++ i) write (ans[i]),putchar ('\n');
return 0;
}
题解 「BZOJ3636」教义问答手册的更多相关文章
- BZOJ3636: 教义问答手册
Description “汉中沃野如关中,四五百里烟蒙蒙.黄云连天夏麦熟,水稻漠漠吹秋风.”——摘自 黄裳<汉中行>“泉岭精神不朽,汉中诸球永生.”——摘自<泉岭精神创立者语录> ...
- BZOJ 3636 教义问答手册 (分治)
题意 一个整数数列,多次询问某段区间[li,ri][l_i,r_i][li,ri]内,选出若干个长度为LLL且不相交的连续段使选出来的数和最大. 分析 首先想朴素的区间DPDPDP 设f[i][j ...
- 题解 「HDU6403」卡片游戏
link Description 桌面上摊开着一些卡牌,这是她平时很爱玩的一个游戏.如今卡牌还在,她却不在我身边.不知不觉,我翻开了卡牌,回忆起了当时一起玩卡牌的那段时间. 每张卡牌的正面与反面都各有 ...
- 题解 「SCOI2016」萌萌哒
link Description 一个长度为 $ n $ 的大数,用 $ S_1S_2S_3 \ldots S_n $表示,其中 $ S_i $ 表示数的第 $ i $ 位,$ S_1 $ 是数的最高 ...
- 题解 「SDOI2017」硬币游戏
题目传送门 Description 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利. 大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了. 同学们觉得要加强 ...
- 题解 「ZJOI2018」历史
题目传送门 Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有 \(n\) 个城市,这 \(n\) 个城市被恰 ...
- 题解「BZOJ4310」跳蚤
题目传送门 Description 现在有一个长度为 \(n\) 的字符串,将其划分为 \(k\) 段,使得这 \(k\) 段每一段的字典序最大子串中字典序最大的字符串字典序尽量小.求出这个字符串. ...
- 题解 「BZOJ2137」submultiple
题目传送门 题目大意 给出 \(M,k\) ,求出 \[\sum_{x|M}\sigma(x)^k \] 给出 \(P_i\),满足 \(n=\prod_{i=1}^{n}a_i^{P_i}\),其中 ...
- 题解 「BZOJ2178」圆的面积并
题目传送门 题目大意 给出 \(n\) 个圆,求它们并的面积大小. \(n\le 10^3\) 思路 如果您不会自适应辛普森法,请戳这里学习 其实我们发现,如果我们设 \(f(x)\) 表示 \(x= ...
随机推荐
- Promise.resolve()与Promise
//Promise.resolve()和Promise.reject()常用来生成已经被决议为失败或者成功的promise案例 //Promise.reject()简单一些,不管传给它什么值,它决议为 ...
- Nginx location 和 proxy_pass路径配置详解
目录 一.Nginx location 基本配置 1.1.Nginx 配置文件 1.2 .Python 脚本 二.测试 2.1.测试 location 末尾存在 / 和 proxy_pass末尾存在 ...
- springboot系列总结(二)---springboot的常用注解
上一篇文章我们简单讲了一下@SpringBootApplication这个注解,申明让spring boot自动给程序进行必要的配置,他是一个组合注解,包含了@ComponentScan.@Confi ...
- vue 引入 echarts 图表 并且展示柱状图
npm i echarts -S 下载 echarts 图表 mian.js 文件 引入图表并且全局挂载 //echarts 图表 import echarts from 'echarts' Vue. ...
- Mybatis-plus<二>通用CRUD,分页
Mybatis-plus<二>通用CRUD,分页 与博客Mybatis-plus<一>为同一个Springboot项目. Demo GitHub下载地址:https://git ...
- SpringBoot快速集成SpringBootAdmin管控台监控服务
SpringBootAdmin是一个针对 Spring Boot 的 Actuator 接口进行 UI 美化封装的监控工具,它可以在列表中浏览所有被监控 spring-boot 项目的基本信息.详细的 ...
- shell中的引号
单引号: 所见即所得 原封不动输出 双引号: 与单引号类似 特殊符号进行解析 ( $ $() `` ! ) 无引号: 与双引号类似 支持通配符( {} * ) 反引号: 优先执行 优先执行里面的命令, ...
- Vue3.x全家桶+vite+TS-搭建Vue3.x项目
目录 一.搭建基础项目 1.vite创建项目 3.运行项目 2.环境变量设置介绍 vite配置多环境打包 二.配置Router 1.安装路由 2.配置路由 3.引入 三.配置Vuex 1.安装vuex ...
- 项目需求分析与建议——NABCD模型
特点一:旧物再利用N:需求:在我们的校园生活中,会遇到许多自己用不到的东西例如,学过的课本.废置的闲置物品等,这些"废物"往往占据着许多空间却不能够发挥自身的价值,通过我们的校园二 ...
- 【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚
万事从最基本的开始. 要想完全掌握 NIO,并不是掌握上面文章([死磕NIO]- NIO基础详解)中的三大组件就可以了,我们还需要掌握一些基本概念,如什么是 IO,5 种IO模型的区别,什么是阻塞&a ...