Description:

奈文摩尔有 \(n\) 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 \(1\) 到 \(n\)。第 \(i\) 个灵魂的战斗力为 \(k_i\),灵魂们以点对的形式为影魔提供攻击力。对于灵魂对 \(i, j\) 来说,若不存在 $k_s\ $ 大于 \(k_i\) 或者 \(k_j\),则会为影魔提供 \(p_1\) 的攻击力。另一种情况,令 \(c\) 为 \(k_{i + 1}, k_{i + 2}, \cdots, k_{j -1}\) 的最大值,若 \(c\) 满足:\(k_i ; c > k_j\),或者 \(k_j lt; c lt; k_i\),则会为影魔提供 \(p_2\) 的攻击力,当这样的 \(c\) 不存在时,自然不会提供这 \(p_2\) 的攻击力;其他情况的点对,均不会为影魔提供攻击力。

影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任意一段区间 \([a, b]\),位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑所有满足 \(a\le ilt;j\le b\) 的灵魂对 \(i, j\) 提供的攻击力之和。

顺带一提,灵魂的战斗力组成一个 \(1\) 到 \(n\) 的排列:\(k_1, k_1, \cdots, k_n\)。

Hint:

对于 \(30\%\) 的数据,\(1\le n, m\le 500\)。

另有 \(30\%\) 的数据,\(p_1 = 2p_2\)。

对于 \(100\%\) 的数据,\(1\le n,m\le 200000, 1\le p_1, p_2\le 1000\)。

Solution:

这题直接统计不好统计

我们反过来考虑每个位置对区间的贡献

首先预处理出每个位置左右第一个大于它的位置

1.\(i​\)对于区间(\(l[i] ,r[i]​\)),有\(p_1​\)的贡献,我们在扫到\(r[i]​\)更新\(l[i]​\)即可

2.\(i\)对于所有区间\((l[i],i+1 \text{~} r[i]-1)\) 有\(p_2\)的贡献,我们在扫到\(l[i]\)时更新\(i+1 \text{~} r[i]-1\)

3.\(i​\)对于所有区间\((l[i]+1\text{~}i-1,r[i])​\) 有\(p_2​\)的贡献,我们在扫到\(r[i]​\)时更新\(l[i]+1\text{~}i-1​\)

然后把询问离线拆成\(l,r\)后按端点排序,每次询问区间\(l~r\)的和,答案就是两次询问相减

注意要特判相邻位置的贡献

update:

今天体育课ysbs给我讲了一个更优秀的方法,实际上没必要处理出每个点的左右边界

对于贡献2,我们只要枚举所有以该点为右端点的区间,单调栈维护最近的大于该点的位置

分为左大于右和左小于右两种情况分别做一次就行,这样稍微方便一些

  1. #include <map>
  2. #include <set>
  3. #include <stack>
  4. #include <cmath>
  5. #include <queue>
  6. #include <cstdio>
  7. #include <cstring>
  8. #include <cstdlib>
  9. #include <iostream>
  10. #include <algorithm>
  11. #define ls p<<1
  12. #define rs p<<1|1
  13. using namespace std;
  14. typedef long long ll;
  15. const ll mxn=1e6+5;
  16. ll n,m,p1,p2,tot,cnt1,cnt2,a[mxn],lt[mxn],rt[mxn],ans[mxn];
  17. ll hd1[mxn],hd2[mxn],tr[mxn<<2],tag[mxn<<2];
  18. struct Q {
  19. ll pos,l,r,id;
  20. }q[mxn];
  21. struct ed {
  22. ll to1,to2,nxt;
  23. }t1[mxn],t2[mxn];
  24. inline ll read() {
  25. char c=getchar(); ll x=0,f=1;
  26. while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
  27. while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
  28. return x*f;
  29. }
  30. inline ll chkmax(ll &x,ll y) {if(x<y) x=y;}
  31. inline ll chkmin(ll &x,ll y) {if(x>y) x=y;}
  32. ll cmp(Q x,Q y) {
  33. return x.pos<y.pos;
  34. }
  35. inline void add1(ll u,ll v) {
  36. t1[++cnt1]=(ed) {v,0,hd1[u]};
  37. hd1[u]=cnt1;
  38. }
  39. inline void add2(ll u,ll v,ll w) {
  40. t2[++cnt2]=(ed) {v,w,hd2[u]};
  41. hd2[u]=cnt2;
  42. }
  43. void push_up(ll p) {
  44. tr[p]=tr[ls]+tr[rs];
  45. }
  46. void push_down(ll l,ll r,ll p) {
  47. if(tag[p]) {
  48. ll mid=(l+r)>>1;
  49. tr[ls]+=(mid-l+1)*tag[p];
  50. tr[rs]+=(r-mid)*tag[p];
  51. tag[ls]+=tag[p];
  52. tag[rs]+=tag[p];
  53. tag[p]=0;
  54. }
  55. }
  56. void update1(ll l,ll r,ll pos,ll val,ll p)
  57. {
  58. if(l==r) {
  59. tr[p]+=val;
  60. return ;
  61. }
  62. ll mid=(l+r)>>1; push_down(l,r,p);
  63. if(pos<=mid) update1(l,mid,pos,val,ls);
  64. else update1(mid+1,r,pos,val,rs);
  65. push_up(p);
  66. }
  67. void update2(ll l,ll r,ll ql,ll qr,ll val,ll p)
  68. {
  69. if(ql<=l&&r<=qr) {
  70. tr[p]+=val*(r-l+1);
  71. tag[p]+=val;
  72. return ;
  73. }
  74. ll mid=(l+r)>>1; push_down(l,r,p);
  75. if(ql<=mid) update2(l,mid,ql,qr,val,ls);
  76. if(qr>mid) update2(mid+1,r,ql,qr,val,rs);
  77. push_up(p);
  78. }
  79. ll query(ll l,ll r,ll ql,ll qr,ll p)
  80. {
  81. if(ql<=l&&r<=qr) return tr[p];
  82. ll mid=(l+r)>>1; push_down(l,r,p); ll res=0;
  83. if(ql<=mid) res+=query(l,mid,ql,qr,ls);
  84. if(qr>mid) res+=query(mid+1,r,ql,qr,rs);
  85. return res;
  86. }
  87. int main()
  88. {
  89. n=read(); m=read(); p1=read(); p2=read(); ll l,r;
  90. for(ll i=1;i<=n;++i) a[i]=read();
  91. for(ll i=1;i<=m;++i) {
  92. l=read(),r=read();
  93. q[i]=(Q){l-1,l,r,i};
  94. q[i+m]=(Q){r,l,r,i+m};
  95. }
  96. stack<ll > st;
  97. for(ll i=1;i<=n;++i) {
  98. while(!st.empty()&&a[st.top()]<a[i]) st.pop();
  99. if(st.empty()) lt[i]=0;
  100. else lt[i]=st.top(); st.push(i);
  101. }
  102. while(!st.empty()) st.pop();
  103. for(ll i=n;i>=1;--i) {
  104. while(!st.empty()&&a[st.top()]<a[i]) st.pop();
  105. if(st.empty()) rt[i]=n+1;
  106. else rt[i]=st.top(); st.push(i);
  107. if(lt[i]+1!=rt[i]) add1(rt[i],lt[i]);
  108. add2(rt[i],lt[i]+1,i-1); add2(lt[i],i+1,rt[i]-1);
  109. }
  110. sort(q+1,q+2*m+1,cmp); ll pos=0;
  111. for(ll i=1;i<=2*m;++i) {
  112. while(pos<q[i].pos) {
  113. ++pos; if(pos-1!=0) update1(1,n,pos-1,p1,1);
  114. for(ll j=hd1[pos];j;j=t1[j].nxt) {
  115. ll v=t1[j].to1;
  116. if(v!=0) update1(1,n,v,p1,1);
  117. }
  118. for(ll j=hd2[pos];j;j=t2[j].nxt) {
  119. ll v=t2[j].to1,w=t2[j].to2;
  120. if(v!=0&&w!=0&&w!=n+1&&v!=n+1) update2(1,n,v,w,p2,1);
  121. }
  122. }
  123. l=q[i].l; r=q[i].r;
  124. ans[q[i].id]=query(1,n,l,r,1);
  125. }
  126. for(ll i=1;i<=m;++i) printf("%lld\n",ans[i+m]-ans[i]);
  127. return 0;
  128. }

[HNOI2017/AHOI2017]影魔的更多相关文章

  1. 「AHOI / HNOI2017」影魔

    「AHOI / HNOI2017」影魔 题目描述 解决这类比较复杂的区间贡献问题关键在于找到计算的对象. 比如这道题,我们计算的对象就是区间中间的最大值. 对于点\(i\),我们找到左边第一个比他大的 ...

  2. 【BZOJ4826】【HNOI2017】影魔(扫描线,单调栈)

    [BZOJ4826][HNOI2017]影魔(扫描线,单调栈) 题面 BZOJ 洛谷 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他 ...

  3. [HNOI/AHOI2017]影魔

    [HNOI/AHOI2017]影魔 题目大意: 有一排\(n(n\le2\times10^5)\)个数\(k_{1\sim n}\).对于点对\((i,j)\),若不存在\(k_s(i<s< ...

  4. 【HNOI2017】影魔

    题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个灵魂,都有着自 ...

  5. BZOJ 4826 【HNOI2017】 影魔

    题目链接:影魔 这道题就是去年序列的弱化版啊…… 我们枚举最大值的位置\(i\),找出左边第一个比\(a_i\)大的位置\(l\),右边第一个比\(a_i\)大的位置\(r\),然后我们分开考虑一下\ ...

  6. 【BZOJ4826】【HNOI2017】影魔

    题意: Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. ...

  7. LOJ#2019. 「AHOI / HNOI2017」影魔

    题意: 在一个序列中 如果有一个子区间 它有一个端点是区间最大值 另一个端点不是这个区间的次大值 就会有p2的贡献 它两个端点分别是最大值次大值 就会有p1的贡献 我们发现这两个条件有一个重合的部分 ...

  8. 【HNOI 2016】序列

    Problem Description 给定长度为 \(n\) 的序列:\(a_1, a_2, \cdots , a_n\),记为 \(a[1 \colon n]\).类似地,\(a[l \colon ...

  9. 「LOJ2000~2023」各省省选题选做

    「LOJ2000~2023」各省省选题选做 「SDOI2017」数字表格 莫比乌斯反演. 「SDOI2017」树点涂色 咕咕咕. 「SDOI2017」序列计数 多项式快速幂. 我们将超过 \(p\) ...

随机推荐

  1. Visual Studio 2017 error: Unable to start program, An operation is not legal in the current state

    For me, the solution (workaround) is to turn off JavaScript debugging on Chrome, which I believe is ...

  2. office之Excel 你会用 Ctrl + E 吗?

    从Excel97至现在的最新版本2016,如果评选Excel中最简单.易用.功能最强大的技巧,非2013版新增的“快速填充”(快捷键 Ctrl+E)莫属.向下拖动复制后,打开下拉菜单,就可以看到它的身 ...

  3. servlet获取多个同名参数

    String[] item = request.getParameterValues("参数名");

  4. Nancy 返回值详解

    简介 Nancy 是一个轻量级的,简单粗暴的framework用来构建基于HTTP的各种服务,兼容.Net和Mono.它的返回值也是多种多样的,适应各种不同的情况.包括Response.AsFile( ...

  5. C#异常断电后重新启动项目出现配置未初始化错误

    转到如截图中所示路径,将其下的数据删掉,就可以启动了.

  6. Multidex(二)之Dex预加载优化

    Multidex(二)之Dex预加载优化 https://www.jianshu.com/p/2891599511ff

  7. poj3889

    看题解之前并不知道怎么搞.. 分治是显然的 但是我不知道怎么判断4个块的位置 发现很简单... 注意14是23旋转得到的 而同时也等价于交换了横纵坐标 所以就可以做了

  8. Office 2010 word无法创建工作文件 请检查临时环境变量 的解决办法

    Office 2010 word无法创建工作文件 请检查临时环境变量 的解决办法 http://hi.baidu.com/netshen/item/207fd935d452e0e9df2221c9 如 ...

  9. BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...

  10. day64 url用法以及django的路由系统

    此篇博客是以备后查的,用到的时候记得过来查找即可! 路由系统:就是我们的django项目创建的时候自带的那个urls.py 它本身里面是映射的对应关系,一个大的列表里面,一个个元祖,元祖里面是url或 ...