bzoj 4540: [Hnoi2016]序列 莫队算法+rmq
来源:互联网 发布:怎么在淘宝买种子 编辑:程序博客网 时间:2024/06/13 21:55
题意
给出一个长度为n的序列和q个询问,没个询问l r表示求[l,r]中每一个子序列的最小值的和。
n,q<=100000
分析
正解是非常玄学的线段树,反正我是不会了,不过据说跑的还没有莫队快……
首先很容易想到离线做,但是莫队要怎么更新呢?总不能O(n)扫一遍吧。
我们假设现在莫队处理到的区间为[l,r],那么我要将其变为[l,r-1],那么就是要减去所有区间[i,r](l< =i<=r)的最小值。那么我们设ls[i]表示往左第一个不大于i的数的下标,那么减去的贡献就相当于
一遍过真爽啊!!!一开始T是因为每次rmq调用了cmath库中的log函数,后面把log预处理了一下就跑的飞快了。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#define N 100005#define ll long longusing namespace std;int n,m,pos[N],f[N][20],a[N],ls[N],nx[N],s[N],logn[N];ll suml[N],sumr[N],ans;struct query{int l,r,id;ll ans;}q[N];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void getrmp(){ for (int i=1;i<=n;i++) f[i][0]=i; for (int i=1;i<=16;i++) for (int j=1;j<=n;j++) if (j+(1<<i)-1<=n) { if (a[f[j][i-1]]<a[f[j+(1<<(i-1))][i-1]]) f[j][i]=f[j][i-1]; else f[j][i]=f[j+(1<<(i-1))][i-1]; } else break;}void prework(){ for (int i=1;i<=n;i++) logn[i]=log(i)/log(2); int head=1,tail=0; for (int i=1;i<=n;i++) { while (head<=tail&&a[s[tail]]>a[i]) tail--; if (head<=tail) ls[i]=s[tail]; s[++tail]=i; suml[i]=suml[ls[i]]+(ll)a[i]*(i-ls[i]); } head=1,tail=0; for (int i=n;i>=1;i--) { while (head<=tail&&a[s[tail]]>a[i]) tail--; if (head<=tail) nx[i]=s[tail]; s[++tail]=i; sumr[i]=sumr[nx[i]]+(ll)a[i]*(nx[i]-i); }}bool cmp(query a,query b){ return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;}bool cmpid(query a,query b){ return a.id<b.id;}int getmin(int l,int r){ int w=logn[r-l+1]; if (a[f[l][w]]<a[f[r-(1<<w)+1][w]]) return f[l][w]; else return f[r-(1<<w)+1][w];}void updatal(int l,int r,int x){ int w=getmin(l,r); ans+=(ll)(sumr[l]-sumr[w]+(ll)a[w]*(r-w+1))*x;}void updatar(int l,int r,int x){ int w=getmin(l,r); ans+=(ll)(suml[r]-suml[w]+(ll)a[w]*(w-l+1))*x;}void solve(){ int l=1,r=1; ans=a[1]; for (int i=1;i<=m;i++) { for (;r<q[i].r;r++) updatar(l,r+1,1); for (;l>q[i].l;l--) updatal(l-1,r,1); for (;r>q[i].r;r--) updatar(l,r,-1); for (;l<q[i].l;l++) updatal(l,r,-1); q[i].ans=ans; }}int main(){ n=read();m=read(); int block=sqrt(n); for (int i=1;i<=n;i++) { a[i]=read(); pos[i]=(i+block-1)/block; } getrmp(); prework(); for (int i=1;i<=m;i++) { q[i].l=read();q[i].r=read(); q[i].id=i; } sort(q+1,q+m+1,cmp); solve(); sort(q+1,q+m+1,cmpid); for (int i=1;i<=m;i++) printf("%lld\n",q[i].ans); return 0;}
0 0
- bzoj 4540: [Hnoi2016]序列 莫队算法+rmq
- bzoj 4540: [Hnoi2016]序列 莫队算法
- BZOJ 4540: [Hnoi2016]序列 莫队算法
- bzoj 4540: [Hnoi2016]序列
- BZOJ 4540 [Hnoi2016]序列
- [bzoj 4542] [Hnoi2016]大数:莫队算法
- bzoj 4542: [Hnoi2016]大数 莫队算法
- [莫队 单调栈] BZOJ 4540 [Hnoi2016]序列
- Bzoj4540:[Hnoi2016]序列:莫队+RMQ
- [bzoj4540][Hnoi2016]序列 莫队+RMQ
- BZOJ 3339: Rmq Problem|莫队算法
- BZOJ 4542([Hnoi2016]序列-莫队)
- [bzoj 4540] [Hnoi2016]序列:离线,线段树,矩阵乘法
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- 4540: [Hnoi2016]序列
- BZOJ 3339/3585 Rmq Problem/mex 莫队算法
- 4542: [Hnoi2016]大数 莫队算法
- java面向对象中的封装、继承和多态
- java读写csv文件
- 带缓存的I/O操作
- 深度学习(二):用CNTK在Python下实现一个简单的FeedForward网络
- 428_IllegalStateException错误
- bzoj 4540: [Hnoi2016]序列 莫队算法+rmq
- Unity 定时器
- OpenCV-Python[第三章]——加法操作与alpha blending
- HOG特征(Histogram of Gradient)
- 429_WebView加载静态资源
- 数据库设计三大范式与BCNF,学习笔记
- 16 - 12 - 05 普里姆(Prim)算法-最小生成树-奥义
- 430_复写WebView的JS监听
- UVA