BZOJ 4540: [Hnoi2016]序列 莫队算法
来源:互联网 发布:咫尺网络微官网 编辑:程序博客网 时间:2024/06/06 02:43
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 1412 Solved: 663
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[s:t]是a[l:r]的子序列。现在有q个询问,每个询问给定两个数l和r,1≤l≤r≤n,求a[l:r]的不同子序列的最小值之和。例如,给定序列5,2,4,1,3,询问给定的两个数为1和3,那么a[1:3]有6个子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],这6个子序列的最小值之和为5+2+4+2+2+2=17。
Input
输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数。接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i个元素的值。接下来q行,每行包含两个整数l和r,代表一次询问。
Output
对于每次询问,输出一行,代表询问的答案。
Sample Input
5 5
5 2 4 1 3
1 5
1 3
2 4
3 5
2 5
Sample Output
28
17
11
11
17
HINT
1 ≤N,Q ≤ 100000,|Ai| ≤ 10^9
Source
好颓废啊,一上午就写了这么一道题,真颓废
一看是一道莫队题,貌似很水的样子,然后也就只看出了是道莫队题,然后就不会转移了
于是看了题解%%%
我再叙述一遍,顺带复习
首先我们发现如果对
那么我们如果每次都去
我们用
那么如果令
那么显然有
就是说一直到
那么怎么计算
那么区间
这段区间的贡献是
于是我们一直跳,一直到找到左端点为
这就相当于一棵树的结构,我们从右边的一个较小值的位置连到他左边的第一个比他更小的值
边权为区间长度乘以右边的那个较小值
于是我们维护一个
就好像我们要求树上两个点的距离,两个点中浅的一个点在深的一个点到根的路径上时
维护两个点到根节点的距离然后相减一样,所以这是有区间相减的性质的
所以我们维护一个
long long call(int l,int r){//考虑左端点对l到r区间的影响 int loc=find(l,r);//find为找区间l,r里最小的那个值的位置(在原来的数列中) return A[loc]*(r-loc+1)+up[l]-up[loc];}
如上所示是一个求
然后再用这个最小值去求右边区间的贡献和左边的
然而为什么我们需要一个
注意到我们的
他是否一定是从
好像不一定吧
然而我们还是可以直接找一下
因为从左端点到右端点的最小值都已经找到了,那么从左端点往右连的边中,不经过这个最小值说不过去了吧
最后一个问题:
因为
此时单调栈里存的也就是第一个小于当前位置的数的位置了,处理完之后把新的数
由于新的数更新,所以之后的数如果找到这个数的话,那么一定是最近的比其小的数
(好像这几句话都是很基础的东西
int top=0; for(register int i=1;i<=n;i++){ while(top&&A[i]<=A[sta[top]])top--;//单增的栈,处理以i结尾 down[i]=down[sta[top]]+A[i]*(i-sta[top]);//栈内存的是一个位置,第一个比当前位置小的位置,而这个位置是一定已经被处理过的 sta[++top]=i;//down存的是以i结尾的一直到根的值 }
#include<bits/stdc++.h>using namespace std;const int inf=0x3f3f3f3f;const int MAXN=100000+10;struct Q{int l,r,blo,id;long long ans;}q[MAXN];int n,m,sta[MAXN],dp[MAXN<<1][20];long long A[MAXN],down[MAXN],up[MAXN];bool cmp(const Q &A,const Q &B){ if(A.blo!=B.blo) return A.blo<B.blo; if(A.r!=B.r) return A.r<B.r; return A.l<B.l;}void init(){ int top=0; for(register int i=1;i<=n;i++){ while(top&&A[i]<=A[sta[top]])top--; down[i]=down[sta[top]]+A[i]*(i-sta[top]); sta[++top]=i; } top=0;sta[top]=n+1; for(register int i=n;i;i--){ while(top&&A[i]<=A[sta[top]])top--; up[i]=up[sta[top]]+A[i]*(sta[top]-i); sta[++top]=i; } }int mn(int x,int y){ if(A[x]<A[y]) return x; else return y;}void get_st(){ A[0]=inf; for(register int i=1;i<=n;i++) dp[i][0]=i; for(register int j=1;(1<<j)<=n;j++) for(register int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=mn(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}int find(int L,int R){ int M=0;while((1<<(M+1))<(R-L+1)) M++; return mn(dp[L][M],dp[R-(1<<M)+1][M]);} long long call(int l,int r){ int loc=find(l,r); return A[loc]*(r-loc+1)+up[l]-up[loc];}long long calr(int l,int r){ int loc=find(l,r); return A[loc]*(loc-l+1)+down[r]-down[loc];}void Mos_Algorithm(){ sort(q+1,q+m+1,cmp); int l=1,r=0; long long tmp=0; for(register int i=1;i<=m;i++){ while(r<q[i].r) tmp+=calr(l,++r); while(r>q[i].r) tmp-=calr(l,r--); while(l>q[i].l) tmp+=call(--l,r); while(l<q[i].l) tmp-=call(l++,r); q[q[i].id].ans=tmp; } for(register int i=1;i<=m;i++) printf("%lld\n",q[i].ans);}int main(){ scanf("%d%d",&n,&m); for(register int i=1;i<=n;i++) scanf("%lld",&A[i]); init();get_st(); int block=sqrt(n); for(register int i=1;i<=m;i++){scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;q[i].blo=(q[i].l-1)/block+1;} Mos_Algorithm(); return 0;}/*5 5 5 2 4 1 3 1 51 32 43 52 5 */
- bzoj 4540: [Hnoi2016]序列 莫队算法
- BZOJ 4540: [Hnoi2016]序列 莫队算法
- bzoj 4540: [Hnoi2016]序列 莫队算法+rmq
- bzoj 4540: [Hnoi2016]序列
- BZOJ 4540 [Hnoi2016]序列
- [bzoj 4542] [Hnoi2016]大数:莫队算法
- bzoj 4542: [Hnoi2016]大数 莫队算法
- [莫队 单调栈] BZOJ 4540 [Hnoi2016]序列
- BZOJ 4542([Hnoi2016]序列-莫队)
- [bzoj 4540] [Hnoi2016]序列:离线,线段树,矩阵乘法
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- 4542: [Hnoi2016]大数 莫队算法
- bzoj 4540: [Hnoi2016]序列 (莫队+ST表+单调栈|线段树)
- 【HNOI2016】序列
- 4540: [Hnoi2016]序列|莫队+ST表
- BZOJ 3781 小B的询问 序列莫队算法
- android网络调试工具Stetho介绍
- 短实习---Java面向对象(练习题)
- 51nod 1289 大鱼吃小鱼
- 仿中国比特币首页趋势图,折线图,k线图
- HDU
- BZOJ 4540: [Hnoi2016]序列 莫队算法
- iOS支持富文本Label控件
- android 跑马灯出现重复跳动、不滚动问题
- Spring Boot --微信企业号开发01-使用新花生壳进行本地开发测试
- MacOS 开发- NSBox
- Spring任务调度两种配置方式
- leetcode---unique-paths---dp
- 高可用方案之二 nginx热机双备
- Python日记【开更关于学习python的点点滴滴】-16.09.14