题目链接:影魔

  这道题就是去年序列的弱化版啊……

  我们枚举最大值的位置\(i\),找出左边第一个比\(a_i\)大的位置\(l\),右边第一个比\(a_i\)大的位置\(r\),然后我们分开考虑一下\(p_1\)和\(p_2\)的贡献。

  首先由于\(a_i\)为最大值,那么左端点不会小于\(l\),右端点不会大于\(r\)。

  容易发现只有左端点为\(l\),右端点为\(r\)才会产生\(p_1\)的贡献。

  然后产生\(p_2\)贡献的有两种:一种是左端点为\(l\),右端点在区间\((i,r)\)中;另一种是左端点区间\((l,i)\)中,右端点为\(r\)。

  还有一种情况需要考虑,就是左端点和右端点差为\(1\),会产生\(p_1\)的贡献。对每个询问直接计算就可以了。

  所以这个问题可以抽象到二维平面上。有一些点和一些线段都有权值,每次询问某个矩形内部的权值和。

  于是离线排序+扫描线+树状数组即可。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 200010 using namespace std;
typedef long long llg; struct data{
int l,r,x,b,z;
data(int A=0,int B=0,int C=0,int D=0,int E=0):l(A),r(B),x(C),b(D),z(E){}
bool operator < (const data &h)const{return x<h.x;}
}s1[maxn<<1],s2[maxn*3];
int n,m,p1,p2,S[maxn],top,ls;
int a[maxn],le[maxn],ri[maxn];
llg ans[maxn],c1[maxn],c2[maxn]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} void add(int x,int y){for(int i=x;i<=n;i+=i&(-i)) c1[i]+=y,c2[i]+=1ll*x*y;}
llg sum(int x){
llg t=0;
for(int i=x;i;i-=i&(-i)) t+=(x+1)*c1[i]-c2[i];
return t;
} int main(){
File("sf");
scanf("%d %d %d %d",&n,&m,&p1,&p2);
a[0]=a[n+1]=n+1; S[top=1]=0;
for(int i=1;i<=n+1;i++){
if(i<=n) a[i]=getint();
while(a[S[top]]<a[i]) ri[S[top--]]=i;
le[i]=S[top]; S[++top]=i;
}
for(int i=1,l,r;i<=m;i++){
l=getint(),r=getint(); ans[i]+=(r-l)*p1;
s1[i]=data(l,r,l-1,i,-1);
s1[i+m]=data(l,r,r,i,1);
}
sort(s1+1,s1+m*2+1);
for(int i=1;i<=n;i++){
if(le[i] && ri[i]<=n) s2[++ls]=data(le[i],le[i],ri[i],0,p1);
if(le[i] && ri[i]>i+1) s2[++ls]=data(i+1,ri[i]-1,le[i],0,p2);
if(ri[i]<=n && i>le[i]+1) s2[++ls]=data(le[i]+1,i-1,ri[i],0,p2);
}
sort(s2+1,s2+ls+1); int n1=1,n2=1;
while(!s1[n1].x) n1++;
for(int i=1;n1<=m*2 && i<=n;i++){
while(n2<=ls && s2[n2].x==i){
add(s2[n2].r+1,-s2[n2].z);
add(s2[n2].l,s2[n2].z),n2++;
}
while(n1<=m*2 && s1[n1].x==i){
ans[s1[n1].b]+=s1[n1].z*(sum(s1[n1].r)-sum(s1[n1].l-1));
n1++;
}
}
for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}

最新文章

  1. webapi swagger自定义 HTTP Header验证用户
  2. 【pymongo】mongodb cursor id not valid error
  3. Node.js 创建HTTP服务器(经过测试,这篇文章是靠谱的T_T)
  4. iOS - UIControl
  5. JSON日期格式处理
  6. 全自动化的 Android 编译管线
  7. JS实现Web网页打印功能(IE)
  8. [转载]vs2012中使用Spring.NET报错:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常
  9. Android项目Tab类型主界面大总结 Fragment+TabPageIndicator+ViewPager
  10. centos 彻底卸载mysql
  11. VS2012破解_序列号
  12. 从零开始学安全(三十四)●百度杯 ctf比赛 九月场 sqli
  13. jQuery设置时间格式
  14. supervisor 结合 Dockerfile ENTRYPOINT
  15. 9、链表 &amp; 状态机 &amp; 多线程
  16. Curry化函数
  17. 将句子表示为向量(下):基于监督学习的句子表示学习(sentence embedding)
  18. 项目中开机自启动的 node-webkit开机自启动
  19. EF那点事
  20. Redis_常用5大数据类型简介

热门文章

  1. EF使用sql语句
  2. element ui里dialog关闭后清除验证条件
  3. C#——WebApi 接口参数传参详解
  4. SpringMVC中参数接收
  5. Django中程序中图片资源的路径问题(static文件夹的放置)
  6. jquery photoClip支持手机端,PC端 本地裁剪图片后上传插件
  7. OSI七层协议与TCP/IP模型
  8. spring boot log4j2与三方依赖库log4j冲突无法初始化问题解决方法
  9. suse日常操作(含suse/rhel内核与发行版对应关系)
  10. Python 操作 mysql数据库的一个小小的基础案例,小白新手,以备后用~~