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 ...
随机推荐
- icmp的程序(ping的实现)
code来源于<网络编程与分层协议设计> chap7 ICMP协议程序设计 ----没有理解,没有编译,只是敲了出来 ping.h #define ICMP_ECHOREPLY 0#def ...
- CSDN - 进程结束后new出的内存会回收吗?
http://blog.csdn.net/stanjiang2010/article/details/5386647 关键词:内存回收
- 【每日Scrum】第八天(4.29) TD学生助手Sprint2
站立会议 组员 今天 签到 刘铸辉 (组长) 绩效考核 Y 刘静 测试用例书写 测试bug报告 测试详细报告 Y 解凤娇 Y 王洪叶 项目可行性报告 项目开发计划书 需求分析(已完成并发布) Y 胡宝 ...
- Spring Boot实现STOMP协议的WebSocket
关注公众号:锅外的大佬 每日推送国外优秀的技术翻译文章,励志帮助国内的开发者更好地成长! WebSocket协议是应用程序处理实时消息的方法之一.最常见的替代方案是长轮询(long polling)和 ...
- php逻辑操作符中&和&&的异同
php有5种算术操作符(+ - * / %),6种赋值操作符(+= -= *= /= %= .=),8种比较操作符(=== < > <= >= != <> !==) ...
- 软考考点---CPU
软考考点---CPU 中央处理器(CPU,Central Processing Unit)是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Un ...
- 图像处理之滤波---滤波在游戏中的应用boxfilter
http://www.yxkfw.com/?p=7810 很有意思的全方位滤波应用 https://developer.nvidia.com/sites/default/files/akamai/ga ...
- swift3.0系列完整demo代码库
https://github.com/soapyigu/Swift30Projects 感谢作者
- javascript JS递归遍历对象 使用for(variable in object)或者叫for/in和forEach方式
1.递归遍历查找特定key值(ie9以下不支持forEach) 原文http://www.cnblogs.com/ae6623/p/5938560.html var obj = { first: &q ...
- 我们将要建立的EasyDarwin开源社区
从12年12月我开始建立EasyDarwin开源项目,已经三年多的时间了,从开始最简单的一个开源流媒体服务器项目,如今已经发展成为目前国内最大的一个流媒体开源社区,截至目前已经有十几个项目在Githu ...