【LG3246】[HNOI2016]序列
【LG3246】[HNOI2016]序列
题面
题解
60pts
对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\)。
那么在左端点在\((lp_i,i]\),右端点在\([i,rp_i)\)的所有区间中,
区间的贡献均为\(a_i\)(之所以取等情况不一样是防止算重或算漏)。
那么对于一个询问\(L,R\),有
\]
100pts
考虑莫队,那么我们的难点主要就是怎么从区间\([L,R]\)转移到区间\([L,R+1]\)。
用ST表查一下\([L,R+1]\)的最小值的位置\(p\),则左端点在\([L,p]\)的区间贡献均为\(a[p]\)。
现在考虑左端点在\([p+1,R+1]\)的贡献,记一个类似于前缀和的东西\(f_i=f_{lp_i}+(i-lp_i)*a[i]\),
则可以算出区间\([p+1,R+1]\)的贡献为\(f_{R+1}-f_p\),因为\(f_i\)相当于求\(i\)的\(lp\),它\(lp\)的\(lp\)...
到\(i\)的贡献,而\(p\)必为某一个转移端点,所以成立。
向\([L-1,R]\)转移同样维护一个\(g_i=g_{rp_i}+(rp_i-i)*a[i]\)。
减法直接减去一个位置对区间的贡献即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar();
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data;
}
typedef long long ll;
const int MAX_N = 1e5 + 5;
const int LEN = 320;
int N, Q, a[MAX_N], bel[MAX_N];
struct Query { int l, r, id; } q[MAX_N], tmp[MAX_N];
bool operator < (const Query &lhs, const Query &rhs) {
	if (bel[lhs.l] == bel[rhs.l]) return (bel[lhs.l] & 1) ? lhs.r < rhs.r : lhs.r > rhs.r;
	else return bel[lhs.l] < bel[rhs.l];
}
int stk[MAX_N], top, lp[MAX_N], rp[MAX_N];
int st[18][MAX_N], bin[18], lg[MAX_N];
int query(int l, int r) {
	int k = lg[r - l + 1];
	if (a[st[k][l]] < a[st[k][r - bin[k] + 1]]) return st[k][l];
	else return st[k][r - bin[k] + 1];
}
ll L[MAX_N], R[MAX_N], ans[MAX_N], Ans;
ll Ladd(int l, int r) {
	int p = query(l - 1, r);
	return 1ll * a[p] * (r - p + 1) + R[l - 1] - R[p];
}
ll Radd(int l, int r) {
	int p = query(l, r + 1);
	return 1ll * a[p] * (p - l + 1) + L[r + 1] - L[p];
} 
int main () {
#ifndef ONLINE_JUDGE
    freopen("cpp.in", "r", stdin);
	freopen("cpp.out", "w", stdout);
#endif
	N = gi(), Q = gi();
	for (int i = 1; i <= N; i++) a[i] = gi();
	for (int i = 1; i <= N; i++) bel[i] = (i - 1) / LEN + 1;
	bin[0] = 1; for (int i = 1; i <= 17; i++) bin[i] = bin[i - 1] << 1;
	for (int i = 2; i <= N; i++) lg[i] = lg[i >> 1] + 1;
	for (int i = 1; i <= N; i++) st[0][i] = i;
	for (int i = 1; bin[i] <= N; i++)
		for (int j = 1; j + bin[i] - 1 <= N; j++)
			if (a[st[i - 1][j]] < a[st[i - 1][j + bin[i - 1]]]) st[i][j] = st[i - 1][j];
			else st[i][j] = st[i - 1][j + bin[i - 1]];
	for (int i = 1; i <= Q; i++) {
		int l = gi(), r = gi();
		q[i] = (Query){l, r, i};
	}
	sort(&q[1], &q[Q + 1]);
	stk[0] = 0;
	for (int i = 1; i <= N; i++) {
		while (a[stk[top]] >= a[i] && top) --top;
		lp[i] = stk[top], stk[++top] = i;
	}
	top = 0, stk[0] = N + 1;
	for (int i = N; i >= 1; i--) {
		while (a[stk[top]] > a[i] && top) --top;
		rp[i] = stk[top], stk[++top] = i;
	}
	for (int i = 1; i <= N; i++) L[i] = L[lp[i]] + 1ll * (i - lp[i]) * a[i];
	for (int i = N; i >= 1; i--) R[i] = R[rp[i]] + 1ll * (rp[i] - i) * a[i];
	int ql = 1, qr = 0;
	for (int i = 1; i <= Q; i++) {
		while (qr < q[i].r) ++qr, Ans += Radd(ql, qr - 1);
		while (ql < q[i].l) Ans -= Ladd(ql + 1, qr), ++ql;
		while (ql > q[i].l) --ql, Ans += Ladd(ql + 1, qr);
		while (qr > q[i].r) Ans -= Radd(ql, qr - 1), --qr;
		ans[q[i].id] = Ans;
	}
	for (int i = 1; i <= Q; i++) printf("%lld\n", ans[i]);
    return 0;
}
【LG3246】[HNOI2016]序列的更多相关文章
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
		4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ... 
- 4540: [Hnoi2016]序列
		4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ... 
- [BZOJ4540][HNOI2016]序列 莫队
		4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ... 
- BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*
		BZOJ4540 Hnoi2016 序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- ... 
- 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈
		[BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ... 
- [Bzoj4540][Hnoi2016] 序列(莫队  + ST表 + 单调队列)
		4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1567 Solved: 718[Submit][Status] ... 
- [HNOI2016]序列 CDQ+DP
		[HNOI2016]序列 CDQ 链接 loj 思路 一个点最小变为l,最大变为r,不变的时候为v 那么j能在i前面就要满足. \(j<i\) \(r[j]<=v[i]\) \(v[j]& ... 
- 题解-[HNOI2016]序列
		题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ... 
- P6604 [HNOI2016]序列 加强版
		*I. P6604 [HNOI2016]序列 加强版 摘自学习笔记 简单树论 笛卡尔树部分例题 I. 和 P6503 比较类似.我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和 ... 
随机推荐
- 【Oracle】存储过程写法小例子
			1.存储过程的基本语法: CREATE OR REPLACE PROCEDURE 存储过程名(param1 in type,param2 out type) IS 变量1 类型(值范围); 变量2 类 ... 
- alwayson监控
			最近大体自己写了点alwayson相关的监控,是通过存储过程的方法,做个笔记如下: --alwayson启用状态 declare @isenabled sql_variant SELECT @isen ... 
- 15. DML, DDL, LOGON 触发器
			触发器可以理解为由特定事件触发的存储过程, 和存储过程.函数一样,触发器也支持CLR,目前SQL Server共支持以下几种触发器: 1. DML触发器, 表/视图级有效,可由DML语句 (INSER ... 
- (matlab)plot画图的颜色线型(转)
			http://wenku.baidu.com/link?url=SVVMVH8QlDIu2hVKDtoBYs6l0CnQvFnFHJJ9yexmYVKQqhz47qIr7aK7LOf8nN0qNdy8 ... 
- svn检出项目,Project *** is already imported into workspace
			1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.如果从svn检出的项目 Import ---- Existing Maven Pro ... 
- for 与forEach的区别
			for循环 for循环,通过下标,对循环中的代码反复执行,功能强大,可以通过index取得元素.在处理比较复杂的处理的时候较为方便. foreach循环 foreach,从头到尾,对于集合中的对象遍历 ... 
- 访问一个HTTPS的网站的大致流程
			浏览器向服务器发送请求,请求中包括浏览器支持的协议,并附带一个随机数. 服务器收到请求后,选择某种非对称加密算法,把数字证书签名公钥.身份信息发送给浏览器,同时也附带一个随机数. 浏览器收到后,验证证 ... 
- 原生JavaScript可以干那些事情
			1.原生JavaScript实现字符串长度截取 function cutstr(str, len) { var temp; var icount = 0; var patrn = /[^\x00-\x ... 
- 【http学习杂记】2017年7月14日
			1. 连接超时 连接超时是tcp协议层次, 此时服务器还没有处理请求数据,也就是说服务器的逻辑开没有执行 2. 请求超时 请求超时属于服务器已经连接成功并开始处理,但是时间比较长,大于你设置的请求超时 ... 
- Hibernate三种状态;query查询;ResultTransformer转换为pojo对象;能够将query语句写在xml中;Criteria查询;ProjectionList总和/f分组等函数
			版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010026901/article/details/24256091 Session操作过程中的po ... 
