【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述
给出一个序列,多次询问一个区间的所有子区间最小值之和。
输入
输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数。接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i个元素的值。接下来q行,每行包含两个整数l和r,代表一次询问。
输出
对于每次询问,输出一行,代表询问的答案。
样例输入
5 5
5 2 4 1 3
1 5
1 3
2 4
3 5
2 5
样例输出
28
17
11
11
17
题解
单调栈+离线+扫描线+树状数组区间修改区间查询
首先把使用单调栈找出每个数左边第一个大于等于它的数的位置 $lp[i]$ 和右边第一个大于它的数的位置 $rp[i]$ 。
然后每个数的贡献为:左端点在 $[lp[i]+1,i]$ ,右端点在 $[i,rp[i]-1]$ 的所有区间。
如果把区间看作二维平面上的点的话,每个数的贡献相当于是一个矩形,查询范围也是一个矩形。因此问题转化为矩形加、查询矩形和。
可以使用树状数组区间修改来维护,具体方法可以参考 【bzoj3132】上帝造题的七分钟 。
然而本题坐标范围较大,不能直接上二维树状数组,需要使用扫描线去掉一维,然后使用树状数组解决。方法和那道题一样,维护 $\sum v_i,\sum x_iv_i,\sum y_iv_i,\sum x_iy_iv_i$ 即可。
因此离线处理,把每个修改矩形、询问矩形都拆成4个点,放到一起排序,然后扫一遍统计答案即可。(一个小技巧:由于区间左端点一定小于等于右端点,因此整个平面只有横坐标小于等于纵坐标的才有意义,因此可以只把询问矩形拆成两个点)
时间复杂度 $O(n\log n)$
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
int n , a[N] , sta[N] , top , lp[N] , rp[N] , tot;
ll ans[N];
struct bit
{
ll v[N];
inline void add(int x , ll a)
{
int i;
for(i = x ; i <= n ; i += i & -i) v[i] += a;
}
inline ll query(int x)
{
int i;
ll ans = 0;
for(i = x ; i ; i -= i & -i) ans += v[i];
return ans;
}
}A , B , C , D;
struct data
{
int x , y , opt , c;
data() {}
data(int p , int q , int r , int s) {x = p , y = q , opt = r , c = s;}
bool operator<(const data &a)const {return y == a.y ? !opt && a.opt : y < a.y;}
}p[N * 6];
inline void modify(int x , int y , ll a)
{
A.add(x , a) , B.add(x , a * x) , C.add(x , a * y) , D.add(x , a * x * y);
}
inline ll solve(int x , int y)
{
return A.query(x) * (x + 1) * (y + 1) - B.query(x) * (y + 1) - C.query(x) * (x + 1) + D.query(x);
}
inline int read()
{
int ret = 0 , f = 0; char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-') , ch = getchar();
while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = getchar();
return f ? -ret : ret;
}
int main()
{
n = read();
int m = read() , i , l , r;
for(i = 1 ; i <= n ; i ++ ) a[i] = read();
top = 0 , sta[0] = 0;
for(i = 1 ; i <= n ; i ++ )
{
while(top && a[i] < a[sta[top]]) top -- ;
lp[i] = sta[top] + 1 , sta[++top] = i;
}
top = 0 , sta[0] = n + 1;
for(i = n ; i ; i -- )
{
while(top && a[i] <= a[sta[top]]) top -- ;
rp[i] = sta[top] - 1 , sta[++top] = i;
}
for(i = 1 ; i <= n ; i ++ )
{
p[++tot] = data(lp[i] , i , 0 , a[i]);
p[++tot] = data(i + 1 , i , 0 , -a[i]);
p[++tot] = data(lp[i] , rp[i] + 1 , 0 , -a[i]);
p[++tot] = data(i + 1 , rp[i] + 1 , 0 , a[i]);
}
for(i = 1 ; i <= m ; i ++ )
{
l = read() - 1 , r = read();
p[++tot] = data(r , r , 1 , i);
p[++tot] = data(l , r , -1 , i);
}
sort(p + 1 , p + tot + 1);
for(i = 1 ; i <= tot ; i ++ )
{
if(p[i].opt) ans[p[i].c] += p[i].opt * solve(p[i].x , p[i].y);
else modify(p[i].x , p[i].y , p[i].c);
}
for(i = 1 ; i <= m ; i ++ ) printf("%lld\n" , ans[i]);
return 0;
}
【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询的更多相关文章
- 【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询
题目描述 JYY有N个平面坐标系中的矩形.每一个矩形的底边都平行于X轴,侧边平行于Y轴.第i个矩形的左下角坐标为(Xi,Yi),底边长为Ai,侧边长为Bi.现在JYY打算从这N个矩形中,随机选出两个不 ...
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- 1082 线段树练习 3 && 树状数组区间修改区间查询
1082 线段树练习 3 题意: 给定序列初值, 要求支持区间修改, 区间查询 Solution 用树状数组, 代码量小, 空间占用小 巧用增量数组, 修改时在 \(l\) 处 $ + val$ , ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- [POJ3468]关于整数的简单题 (你想要的)树状数组区间修改区间查询
#include <cstdio> #include <algorithm> #include <cstring> #include <cctype> ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
随机推荐
- Java设计模式(21)——行为模式之备忘录模式(Memento)
一.概述 概念 UML简图 角色 根据下图得到角色 备忘录角色(Memento).发起人角色(Originator).负责人角色(Caretaker) 二.实践 使用白箱实现,给出角色的代码: 发起人 ...
- 成都Uber优步司机奖励政策(2月1日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 【机器学习笔记】自组织映射网络(SOM)
什么是自组织映射? 一个特别有趣的无监督系统是基于竞争性学习,其中输出神经元之间竞争激活,结果是在任意时间只有一个神经元被激活.这个激活的神经元被称为胜者神经元(winner-takes-all ne ...
- mysql int类型的长度值
整数类型的存储和范围(来自mysql手册) 类型 字节 最小值 最大值 (带符号的/无符号的) (带符号的/无符号的) TINYINT 1 -128 127 0 255 SMALLIN ...
- 开胃小菜——impress.js代码详解
README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...
- react-native windows系统 红屏报assets缺失 500错误
指定版本,react-native是facebook用mac系统开发的,windows系统兼容较差,新版本更是问题很多, 相对老版本更加稳定 react-native init demo --vers ...
- cf#512 C. Vasya and Golden Ticket
题目链接 http://codeforces.com/contest/1058/problem/C 这题还是暴力最方便,和的情况最多有n*a[i] 900种把每种都试一遍 #include<b ...
- 【第二章】Shell 变量
一.什么是变量? 变量就是一个固定的字符串(也可以是字符.数字的组合)代替更多.更复杂的内容,该内容可能是变量.路径.字符串等其他内容. 变量就是程序中保存用户数据的一块内存空间,而变量名就是这块内存 ...
- 2018科大讯飞AI营销算法大赛全面来袭,等你来战!
AI技术已成为推动营销迭代的重要驱动力.AI营销高速发展的同时,积累了海量的广告数据和用户数据.如何有效应用这些数据,是大数据技术落地营销领域的关键,也是检测智能营销平台竞争力的标准. 讯飞AI营销云 ...
- The Activation Function in Deep Learning 浅谈深度学习中的激活函数
原文地址:http://www.cnblogs.com/rgvb178/p/6055213.html 版权声明:本文为博主原创文章,未经博主允许不得转载. 激活函数的作用 首先,激活函数不是真的要去激 ...