bzoj 4540: [Hnoi2016]序列 莫队算法
来源:互联网 发布:淘宝网折叠床单人价格 编辑:程序博客网 时间:2024/06/06 12:49
内测的时候不知道为什么死活想不出来QAQ。。。。
然后看完题解发现傻逼题。。T_T。。。
yy了一个线段树做法(仅理论),在区间[l,r]中保存以mid为中心向两侧的一个单调递减的数组,空间NlogN,显然只有这一个数组中的数对[l,r]的答案有贡献,然后统计一下前缀和二分查找不知道行不行。。。这样应该是O(Nlog^2N)的。
莫队就简单多了。首先用单调栈求出left[i]表示i左边第一个<=a[i]的数(为了不重不漏要让right[i]表示i右边第一个>a[i]的数)。我们发现对于i,(left[i],right[i])为i的势力范围。比如加入一个左端点l,我们发现有[l,right[l]),[right[l],right[right[l]])这些的答案发生了变化。显然这是一个前缀和,预处理一下就好了。
但是这是有终止条件的,因为[l,r]中的最小值的right显然超过了r,把这个特判掉就好了。具体要用rmq求最小值。
AC代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 100005#define ll long longusing namespace std;int n,m,a[N],bin[25],f[17][N],q[N],blg[N],lf[N],rg[N],lg2[N];ll now,ans[N],cl[N],cr[N]; struct node{ int x,y,id; }b[N];int read(){int x=0; bool flag=0; char ch=getchar();while (ch<'0' || ch>'9'){ if (ch=='-') flag=1; ch=getchar(); }while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }return flag?-x:x;}int rmq(int x,int y){int k=lg2[y-x+1];return (a[f[k][x]]<a[f[k][y-bin[k]+1]])?f[k][x]:f[k][y-bin[k]+1];}bool cmp(const node &u,const node &v){return blg[u.x]<blg[v.x] || blg[u.x]==blg[v.x] && u.y<v.y; }void mdyl(int l,int r,int k){int t=rmq(l,r); now+=k*(cr[l]-cr[t]+(ll)a[t]*(r-t+1));}void mdyr(int l,int r,int k){int t=rmq(l,r); now+=k*(cl[r]-cl[t]+(ll)a[t]*(t-l+1));}int main(){n=read(); m=read(); int i,j;for (i=1; i<=n; i++) a[i]=read();for (i=1; i<=n; i++) f[0][i]=i;lg2[1]=0; bin[0]=1; bin[1]=2;for (i=1; i<=16; i++){bin[i+1]=bin[i]<<1;for (j=bin[i]; j<=bin[i+1] && j<=n; j++) lg2[j]=i;for (j=1; j<=n; j++){f[i][j]=f[i-1][j];if (j+bin[i-1]<=n && a[f[i-1][j+bin[i-1]]]<a[f[i][j]])f[i][j]=f[i-1][j+bin[i-1]];}}a[0]=a[n+1]=-1000000001;q[j=1]=0;for (i=1; i<=n; i++){while (a[i]<a[q[j]]){ rg[q[j]]=i; j--; }lf[i]=q[j]; q[++j]=i;}while (j>1) rg[q[j--]]=n+1;for (i=1; i<=n; i++) cl[i]=cl[lf[i]]+(ll)a[i]*(i-lf[i]);for (i=n; i; i--) cr[i]=cr[rg[i]]+(ll)a[i]*(rg[i]-i);int sz=(int)sqrt(n);for (i=1; i<=n; i++) blg[i]=(i-1)/sz;for (i=1; i<=m; i++){b[i].x=read(); b[i].y=read(); b[i].id=i;}sort(b+1,b+m+1,cmp);int l=1,r=1; now=a[1];for (i=1; i<=m; i++){while (l>b[i].x) mdyl(--l,r,1); while (r<b[i].y) mdyr(l,++r,1);while (l<b[i].x) mdyl(l++,r,-1); while (r>b[i].y) mdyr(l,r--,-1);ans[b[i].id]=now;}for (i=1; i<=m; i++) printf("%lld\n",ans[i]);return 0;}
by lych
2016.4.22
0 0
- 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的询问 序列莫队算法
- 蛇形填数
- 常用正则表达式 备忘
- Visual Studio Visual C++
- uva156
- 【LeetCode】LeetCode——第12题:Integer to Roman
- bzoj 4540: [Hnoi2016]序列 莫队算法
- 递归系列之入门题二
- Java基础(五)---局部变量、全局变量、静态变量、final变量、静态常量、静态方法
- Android中Scrollview、ViewPager、ListView冲突问题 (亲测可用)
- KnowRob安装过程中的相关问题记录
- 读薄经典——《程序员修炼之道》
- 二叉树创建以及遍历方式
- 奇异值分解(SVD)原理详解及推导 (转)
- 远程控制的完善—遇到问题与解决方案