莫队好题啊

莫队来做这个题的难点就是考虑如何在\(O(1)\)时间内由\([l,r]\)转移到\([l,r+1]\)

显然加入\(r+1\)这个数之后会和之前所有的位置都产生一个区间,就是要去快速求出这个区间的和

我们先利用单调栈,扫出每个点往左往右都能扩展到哪里,在处理出一个数组\(dp[i]\)表示从\(1\),\(2\),\(3\)$$...$ \(i-1\),\(i\)与\(i\)形成的所有区间最小值的和

有了这个单调栈处理出来的东西就很好处理了

之后我们考虑添加\(r+1\)这个点,我们先用\(st\)查出\([l,r+1]\)的最小值\(x\)和最小值的位置\(t\),之后就分成了两段

  1. \([l,t]\)都是按照整个区间的最小值来算的,于是直接就是\((t-l+1)\times x\)

  2. \([t+1,r+1]\)是有所不同的,但是这个时候我们直接用\(dp[r+1]-dp[t]\)就可以表示出来了

之后有几个坑点

  1. 莫队转移的之后要时刻保证\(l<r\)

  2. \(add(i++)\),尽管穿进去的值是\(i\),但是如果再调用全局变量会是\(i+1\)

代码

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cmath>
  6. #define re register
  7. #define LL long long
  8. #define maxn 100005
  9. inline int read()
  10. {
  11. re char c=getchar();int x=0,r=1;
  12. while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
  13. while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x*r;
  14. }
  15. struct Ask{int x,y,rk;}a[maxn];
  16. LL Ans[maxn];
  17. int St[maxn][18],log_2[maxn],t[maxn][18];
  18. int ls[maxn],rs[maxn],st[maxn],top;
  19. LL dp[maxn],f[maxn];
  20. LL ans;
  21. int n,m,sz,l,r;
  22. inline std::pair<int,int> ask(int L,int R)
  23. {
  24. int k=log_2[R-L+1];
  25. if(St[L][k]<St[R-(1<<k)+1][k]) return std::make_pair(t[L][k],St[L][k]);
  26. return std::make_pair(t[R-(1<<k)+1][k],St[R-(1<<k)+1][k]);
  27. }
  28. inline int cmp(Ask A,Ask B){if(A.x/sz==B.x/sz) return A.y<B.y;return A.x<B.x;}
  29. inline void solve_r(int x,LL opt)
  30. {
  31. LL now=dp[x]; std::pair<int,int> pii=ask(l,x);
  32. now=now-(LL)dp[pii.first]+(LL)pii.second*(LL)(pii.first-l+1);ans+=opt*now;
  33. }
  34. inline void solve_l(int x,LL opt)
  35. {
  36. LL now=f[x]; std::pair<int,int> pii=ask(x,r);
  37. now=now-(LL)f[pii.first]+(LL)pii.second*(LL)(r-pii.first+1);ans+=opt*now;
  38. }
  39. int main()
  40. {
  41. n=read(),m=read();memset(St,20,sizeof(St));
  42. for(re int i=1;i<=n;i++) St[i][0]=read(),t[i][0]=i;
  43. for(re int i=2;i<=n;i++) log_2[i]=1+log_2[i>>1];
  44. for(re int j=1;j<=17;j++)
  45. for(re int i=1;i+(1<<j)-1<=n;i++)
  46. if(St[i][j-1]<St[i+(1<<(j-1))][j-1]) St[i][j]=St[i][j-1],t[i][j]=t[i][j-1];
  47. else St[i][j]=St[i+(1<<(j-1))][j-1],t[i][j]=t[i+(1<<(j-1))][j-1];
  48. sz=std::sqrt(n);
  49. for(re int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(),a[i].rk=i;
  50. std::sort(a+1,a+m+1,cmp);
  51. for(re int i=1;i<=n;i++) {while(top&&St[st[top]][0]>St[i][0]) rs[st[top]]=i,top--;st[++top]=i;}
  52. while(top) rs[st[top]]=n+1,top--;
  53. for(re int i=n;i;--i) {while(top&&St[st[top]][0]>St[i][0]) ls[st[top]]=i,top--;st[++top]=i;}
  54. while(top) ls[st[top]]=0,top--;
  55. for(re int i=1;i<=n;i++) dp[i]=(LL)St[i][0]*(LL)(i-ls[i])+dp[ls[i]];
  56. for(re int i=n;i;--i) f[i]=(LL)St[i][0]*(LL)(rs[i]-i)+f[rs[i]];
  57. l=1,r=1,ans=St[1][0];
  58. for(re int i=1;i<=m;i++)
  59. {
  60. while(l>a[i].x) solve_l(--l,1);
  61. while(r<a[i].y) solve_r(++r,1);
  62. while(l<a[i].x) solve_l(l++,-1);
  63. while(r>a[i].y) solve_r(r--,-1);
  64. Ans[a[i].rk]=ans;
  65. }
  66. for(re int i=1;i<=m;i++) printf("%lld\n",Ans[i]);
  67. return 0;
  68. }

【[HNOI2016]序列】的更多相关文章

  1. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]

    4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...

  2. 【LG3246】[HNOI2016]序列

    [LG3246][HNOI2016]序列 题面 洛谷 题解 60pts 对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\). 那么 ...

  3. 4540: [Hnoi2016]序列

    4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ...

  4. [BZOJ4540][HNOI2016]序列 莫队

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...

  5. BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*

    BZOJ4540 Hnoi2016 序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- ...

  6. 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈

    [BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...

  7. [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1567  Solved: 718[Submit][Status] ...

  8. [HNOI2016]序列 CDQ+DP

    [HNOI2016]序列 CDQ 链接 loj 思路 一个点最小变为l,最大变为r,不变的时候为v 那么j能在i前面就要满足. \(j<i\) \(r[j]<=v[i]\) \(v[j]& ...

  9. 题解-[HNOI2016]序列

    题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...

  10. P6604 [HNOI2016]序列 加强版

    *I. P6604 [HNOI2016]序列 加强版 摘自学习笔记 简单树论 笛卡尔树部分例题 I. 和 P6503 比较类似.我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和 ...

随机推荐

  1. 请比较throw 合throws的区别

    throw语句用在方法体内,表示抛出异常.throws语句用在方法声明的后面,表示再抛出异常,由该方法的调用者来处理.throws主要声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常. ...

  2. mybatis之使用注解

    注解 使用对象 相对应的 XML 描述 @CacheNamespace 类 <cache> 为给定的命名空间(比如类)配置缓存.属性有:implemetation, eviction, f ...

  3. zookeeper 选举

    选举概述: 1.启动时期的选举 所有的服务器状态为 LOOKING. 1.1.每个Server 会投出一票(投票规则为:SID.ZXID ,即 服务器ID 和 最大事务ID). 1.2.处理选票 (A ...

  4. C# SpinWait

    其实SpinWait的code 非常简单,以前看过很多遍,但是从来都没有整理过,整理也是再次学习吧. 我们先看看SpinWait的一些评论或者注意点吧:如果等待某个条件满足需要的时间很短,而且不希望发 ...

  5. JavaWeb学习总结(十):Session简单使用

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...

  6. react阻止默认事件

    return false无效  必须 preventDefault

  7. 浏览器根对象document之方法概述

    1.1 节点 筛选 getRootNode返回上下文的根节点. querySelector返回文档中匹配指定 CSS 选择器的第一个元素. querySelectorAll返回文档中匹配指定 CSS ...

  8. windows 7 Alt+Tab 的风格改成 XP 风格

    1.开始菜单-运行-输入“regedit”. 2.找到这个位置“[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explore ...

  9. maskView遮罩中多张图片的动画

    maskView遮罩中多张图片的动画 说明 用多张图片做遮罩效率极高,非常好理解,而且极其美观! 效果图 素材 源码 // // ViewController.m // FeedBack // // ...

  10. SQL脚本运行

    $v=New-Object -ComObject wscript.shell#也可以使用反单引号(`)字符来强制PowerShell将单引号或双引号解释为文本,0不显示命令提示符窗口$v.run(&q ...