bzoj4540
莫队+st表
据说这是经典问题,但是我不会。。。
问题在于莫队怎么算贡献,每次移动一个位置,现在为[l,r],那么就增加了[l-1,r),r的贡献,怎么算呢?我们预处理fl,fr,fl[i]表示以i为开头的前缀和,fr表示以i为结尾的后缀和,这个东西能够相减,但也不是完全满足
每次我们计算贡献的时候,设最小值的位置为p,那么对于右端点来说,贡献就是fr[r]-fr[p]+(p - l + 1) * a[p],这也是因为不完全满足可减性,因为求前缀和是fr[i]=(i - l[i] + 1) * a[i] + fr[l[i]-1],那么满足可减性是在每个l[i]的时候可以减,又因为p作为最小值肯定是处于一个l的位置,那么就能减了,而到l的贡献就是p作为最小值。
理解得还不是很透彻 我一直以为我的单调栈是左闭右闭的,竟然是左开右闭的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + ;
int n, m, block, l = , r, top;
ll sum;
int st[N], Log[N], f[N][], L[N], R[N];
ll fl[N], fr[N], a[N], ans[N];
struct query {
int l, r, id;
bool friend operator < (const query &a, const query &b) {
return (a.l - ) / block == (b.l - ) / block ? a.r < b.r : (a.l - ) / block < (b.l - ) / block;
}
} q[N];
inline int rd()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
int Min(int x, int y)
{
return a[x] < a[y] ? x : y;
}
int rmq(int l, int r)
{
int x = Log[r - l + ];
return Min(f[l][x], f[r - ( << x) + ][x]);
}
void addl(int l, int r, ll f)
{
int p = rmq(l, r);
sum += f * (fl[l] - fl[p] + a[p] * (ll)(r - p + ));
}
void addr(int l, int r, ll f)
{
int p = rmq(l, r);
sum += f * (fr[r] - fr[p] + a[p] * (ll)(p - l + ));
}
int main()
{
n = rd();
m = rd();
block = sqrt(n);
for(int i = ; i <= n; ++i)
{
a[i] = rd();
f[i][] = i;
}
for(int i = ; i <= n; ++i) Log[i] = Log[i >> ] + ;
for(int j = ; j <= ; ++j)
for(int i = ; i + ( << j) <= n + ; ++i)
f[i][j] = Min(f[i][j - ], f[i + ( << (j - ))][j - ]);
for(int i = ; i <= m; ++i)
{
q[i].l = rd();
q[i].r = rd();
q[i].id = i;
}
sort(q + , q + m + );
for(int i = ; i <= n; ++i)
{
L[i] = R[i] = i;
while(top && a[st[top]] > a[i])
{
R[st[top - ]] = R[st[top]];
L[i] = L[st[top]];
--top;
}
st[++top] = i;
}
while(top)
{
R[st[top - ]] = R[st[top]];
--top;
}
for(int i = ; i <= n; ++i) fr[i] = fr[L[i] - ] + (ll)(i - L[i] + ) * a[i];
for(int i = n; i; --i) fl[i] = fl[R[i] + ] + (ll)(R[i] - i + ) * a[i];
l = ;
r = ;
for(int i = ; i <= m; ++i)
{
while(r < q[i].r) addr(l, ++r, );
while(r > q[i].r) addr(l, r--, -);
while(l < q[i].l) addl(l++, r, -);
while(l > q[i].l) addl(--l, r, );
ans[q[i].id] = sum;
}
for(int i = ; i <= m; ++i) printf("%lld\n", ans[i]);
return ;
}
莫队一定要先动r
bzoj4540的更多相关文章
- 【bzoj4540】 Hnoi2016—序列
http://www.lydsy.com/JudgeOnline/problem.php?id=4540 (题目链接) 题意 给出$n$个数的序列,$m$个询问,每次询问一段区间$[l,r]$,问$[ ...
- 【BZOJ4540】【HNOI2016】序列(莫队)
[BZOJ4540][HNOI2016]序列(莫队) 题面 BZOJ 洛谷 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤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]序列
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- [bzoj4540][Hnoi2016][序列] (莫队算法+单调栈+st表)
Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...
- [luogu3246][bzoj4540][HNOI2016]序列【莫队+单调栈】
题目描述 给定长度为n的序列:a1,a2,...,an,记为a[1:n].类似地,a[l:r](1<=l<=r<=N)是指序列:al,al+1,...,ar-1,ar.若1<= ...
- bzoj4540 序列 (单调栈+莫队+rmq)
首先,如果我知道[l,r],要转移到[l,r+1]的时候,就是加上以r+1为右端点,[l,r+1]为左端点的区间的最小值,其他情况和这个类似 考虑这玩意怎么求 右端点固定的话,我左端点越往左走,这个最 ...
- [BZOJ4540][HNOI2016]序列 莫队
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
随机推荐
- 计算机的一些经典书籍CS经典书单
c++: <c++程序设计> <c++primer> <effective c++> <more effective c++> <深入探索c++对 ...
- python(20)- 列表生成式和生成器表达式练习Ⅱ
题目一: 有两个列表,分别存放来老男孩报名学习linux和python课程的学生名字linux=['钢弹','小壁虎','小虎比','alex','wupeiqi','yuanhao']python= ...
- Python操作MySQL:pymysql和SQLAlchemy
本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...
- 简单理解javascript中的原型对象,实现对之间共享属性和行为
javascript中提供了构造函数.可以方便的创建对象. 典型的构造函数例如以下: function Person(name, age) { this.name = name; this.age = ...
- How to reset your password in Ubuntu
There are many reasons you might want to reset a password: Someone gave you a computer with Ubuntu i ...
- start-dfs.sh 和 start-all.sh的区别
start-dfs.sh 只启动namenode 和datanode, start-all.sh还包括yarn的resourcemanager 和nodemanager 之前就所以因为只启动了star ...
- 轻松搞定RabbitMQ(六)——主题
转自 http://blog.csdn.net/xiaoxian8023/article/details/48806871 翻译地址:http://www.rabbitmq.com/tutorials ...
- linux下apache https 虚拟主机配置
如果单纯仅仅想在数据传输时加密传输,那么ssl证书是不须要认证的,可是浏览器打开时会有警告信息.如果我们做的不是一个公众产品那么也还好啦. 例如以下是今天学习时的一个笔记,事实上我用的是真实环境. 环 ...
- Java Web Start
1. JNLP 2. Security issue: https://java.com/en/download/help/win_controlpanel.xml Windows 7, Vista C ...
- erlang启动参数记录
不管在erlang的shell下还是脚本里,启动参数都是非常有用的,抽空儿整理下erlang的常用启动参数: +A size 异步线程池的线程数,范围为0~1024,默认为10 +P Number ...