Description

题库链接

给你一个长度为 \(n\) 的序列 \(A\) ,给出 \(q\) 组询问。每次询问 \([l,r]\) ,求该区间内所有的子序列中最小值的和。

\(1\leq n,q\leq 100000,|A_i|\leq 10^9\)

Solution

考虑把右端点右移时,会产生 \(r-l+1\) 个新的区间,我们可以来统计这 \(r-l+1\) 个区间的最小值和。

记 \(pre_i\) 为从第 \(i\) 位往左走第一个值比 \(A_i\) 小的位置。

显然在 \(l'\in(pre_r,r]\) 的区间 \([l',r]\) 中的最小值为 \(A_r\) 。

我们可以用这个性质做一遍前缀。记 \(sum_i\) 为右端点为 \(i\) 时,左端点在 \([1,i]\) 这段区间内所有区间中最小值的和。很容易用单调栈预处理出来。

那么对于移动右端点时,我们记 \(loc\) 为这段区间内的最小值所在的位置,显然移动右端点产生的贡献为 \(sum_r-sum_{loc}+A_{loc}\cdot(loc-l+1)\) 。

查询最小值可以用 \(st\) 表来解决。

对于移动左端点也类似,从右往左处理就好了。其余的就用莫队来实现。

Code

//It is made by Awson on 2018.2.12
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); } #define log2 LOG
int n, q, lim, block, a[N+5], log2[N+5], pre[N+5], nex[N+5], f[N+5][20], bin[25];
LL suml[N+5], sumr[N+5], ans[N+5];
int s[N+5], top;
struct tt {
int l, r, id;
bool operator < (const tt &b) const {return l/block == b.l/block ? r < b.r : l < b.l; }
}qry[N+5]; int query(int l, int r) {int lim = log2[r-l+1]; return a[f[l][lim]] < a[f[r-bin[lim]+1][lim]] ? f[l][lim] : f[r-bin[lim]+1][lim]; }
LL movel(int l, int r) {int loc = query(l, r); return sumr[l]-sumr[loc]+1ll*a[loc]*(r-loc+1); }
LL mover(int l, int r) {int loc = query(l, r); return suml[r]-suml[loc]+1ll*a[loc]*(loc-l+1); }
void work() {
read(n), read(q); for (int i = 1; i <= n; i++) read(a[i]), f[i][0] = i;
log2[0] = -1; for (int i = 1; i <= n; i++) log2[i] = log2[i>>1]+1;
bin[0] = 1; for (int i = 1; i <= 20; i++) bin[i] = bin[i-1]<<1;
lim = log2[n], block = sqrt(n);
for (int i = 1; i <= n; i++) {
while (top != 0 && a[s[top]] >= a[i]) --top;
pre[i] = top == 0 ? 0 : s[top]; s[++top] = i;
}
s[top = 0] = 0;
for (int i = n; i >= 1; i--) {
while (top != 0 && a[s[top]] >= a[i]) --top;
nex[i] = top == 0 ? n+1 : s[top]; s[++top] = i;
}
for (int i = 1; i <= n; i++) suml[i] = suml[pre[i]]+1ll*(i-pre[i])*a[i];
for (int i = n; i >= 1; i--) sumr[i] = sumr[nex[i]]+1ll*(nex[i]-i)*a[i];
for (int i = 1; i <= lim; i++) for (int j = 1; j <= n; j++) {
if (j+bin[i-1] > n) break;
f[j][i] = a[f[j][i-1]] < a[f[j+bin[i-1]][i-1]] ? f[j][i-1] : f[j+bin[i-1]][i-1];
}
for (int i = 1; i <= q; i++) read(qry[i].l), read(qry[i].r), qry[i].id = i;
sort(qry+1, qry+1+q);
int curl = 1, curr = 0; LL now = 0;
for (int i = 1; i <= q; i++) {
int l = qry[i].l, r = qry[i].r;
while (curr < r) ++curr, now += mover(curl, curr);
while (curl > l) --curl, now += movel(curl, curr);
while (curr > r) now -= mover(curl, curr), --curr;
while (curl < l) now -= movel(curl, curr), ++curl;
ans[qry[i].id] = now;
}
for (int i = 1; i <= q; i++) writeln(ans[i]);
}
int main() {
work(); return 0;
}

[HNOI 2016]序列的更多相关文章

  1. bzoj 4540 [HNOI 2016] 序列 - 莫队算法 - Sparse-Table - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定一个长度为$n$的序列.询问区间$[l, r]$的所有不同的子序列的最小值的和. 这里的子序列是连续的.两个子序列不同当且仅当它们的左端点或右端点不同. ...

  2. [HNOI 2016]树

    Description 题库链接 给你一棵 \(N\) 个节点根节点为 \(1\) 的有根树,结点的编号为 \(1\sim N\) :我们称这颗树为模板树.需要通过这棵模板树来构建一颗大树.构建过程如 ...

  3. 【HNOI 2016】序列

    Problem Description 给定长度为 \(n\) 的序列:\(a_1, a_2, \cdots , a_n\),记为 \(a[1 \colon n]\).类似地,\(a[l \colon ...

  4. 「HNOI 2016」 序列

    \(Description\) 给你一个序列,每次询问一个区间,求其所有子区间的最小值之和 \(Solution\) 这里要用莫队算法 首先令\(val\)数组为原序列 我们考虑怎么由一个区间\([l ...

  5. hnoi 2016 省选总结

    感觉省选好难的说...反正我数据结构太垃圾正解想到了也打不出来打一打暴力就滚粗了! DAY1 0+20+30 DAY2 60-20+0+60 最后170-20分,暴力分还是没有拿全! 然而这次是给了5 ...

  6. HNOI 2016 省队集训日记

    第一天 DeepDarkFantasy 从东京出发,不久便到一处驿站,写道:日暮里.  ——鲁迅<藤野先生> 定义一个置换的平方为对1~n的序列做两次该置换得到的序列.已知一个置换的平方, ...

  7. 【HNOI 2016】网络

    Problem Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器 ...

  8. [BZOJ 4537][Hnoi 2016]最小公倍数

    传送门 并查集+分块 看到题目可以想到暴力做法, 对于每个询问, 将所有a和b小于等于询问值的的边加入图中(用并查集), 如果询问的u和v在一个联通块中, 且该联通块的maxa和maxb均等与询问的a ...

  9. 【BZOJ 4539】【HNOI 2016】树

    http://www.lydsy.com/JudgeOnline/problem.php?id=4539 今天测试唯一会做的一道题. 按题目要求,如果暴力的把模板树往大树上仍,最后得到的大树是$O(n ...

随机推荐

  1. python IDLE中反斜杠显示为人民币符号¥的解决办法

    改换英文字体即可

  2. 201621123031 《Java程序设计》第13周学习总结

    作业13-网络 1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被 ...

  3. Trie树(转)

    原文http://www.cnblogs.com/TheRoadToTheGold/p/6290732.html 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看 ...

  4. Microsoft dynamic 批量更新

    //批量处理 ExecuteMultipleRequest multipleRequest = new ExecuteMultipleRequest() { Settings = new Execut ...

  5. angular2 学习笔记 ( 4.0 初探 )

    目前是 4.0.0-rc.2. 刚好有个小项目要开发,就直接拿它来试水啦. 更新 cli 到最新版, 创建项目, 然后 follow https://github.com/angular/angula ...

  6. maven入门(7)maven项目(组件)的坐标

    1.为什么要定义Maven坐标      在我们开发Maven项目的时候,需要为其定义适当的坐标,这是Maven强制要求的.在这个基础上,其他Maven项目才能应用该项目生成的构件. 2.Maven坐 ...

  7. Window7系统下安装jdk

    根据电脑的操作系统下载相对于的jdk版本(32位或64位),我安装的是:java_jdk1.7 [计算机]——[属性]——[高级系统设置]——高级——[环境变量] 系统变量——>新建JAVA_H ...

  8. Mysql启动时提示:Another MySQL daemon already running with the same unix socket.

    场景:vmvare虚拟机.centos7.mysql5.7 解决: mv /var/lib/mysql/mysql.sock /var/lib/mysql/mysql.sock.bak 参考: htt ...

  9. ActiveMQ学习系列(一)

    一.JMS规范 JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消 ...

  10. [SHOI2009] 会场预约 - Treap

    Description PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也 ...