「AHOI / HNOI2017」影魔

题目描述

解决这类比较复杂的区间贡献问题关键在于找到计算的对象。

比如这道题,我们计算的对象就是区间中间的最大值。

对于点\(i\),我们找到左边第一个比他大的位置\(L\),以及右边第一个比他大的位置\(R\)。当\(L,R\)同时被询问的区间包含是,\(i\)就会贡献\(p_1\)。当固定左端点为\(L\),右端在\([i+1,R-1]\)之间的时候会贡献\(p_2\);固定右端点\(R\)是同理。还要额外加上\(i,i+1\)贡献的\(p_1\)。

具体实现就可以使用扫描线+树状数组之类的方法。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 200005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m;
ll p1,p2;
int a[N];
int L[N],R[N]; void pre() {
int st[N],top;
st[top=0]=0;
for(int i=1;i<=n;i++) {
while(top&&a[st[top]]<a[i]) top--;
L[i]=st[top]+1;
st[++top]=i;
}
st[top=0]=n+1;
for(int i=n;i>=1;i--) {
while(top&&a[st[top]]<a[i]) top--;
R[i]=st[top]-1;
st[++top]=i;
}
} struct query {
int l,r;
int id;
bool operator <(const query &a)const {return l<a.l;}
}q[N];
bool cmpl(const query &a,const query &b) {return a.l<b.l;}
bool cmpL(const query &a,const query &b) {return a.l>b.l;}
bool cmpR(const query &a,const query &b) {return a.r<b.r;} struct Bit {
ll tem[N];
int low(int i) {return i&(-i);}
void add(int v,int f) {for(int i=v;i<=n;i+=low(i)) tem[i]+=f;}
ll ask(int v) {
ll ans=0;
for(int i=v;i;i-=low(i)) ans+=tem[i];
return ans;
}
void Init() {memset(tem,0,sizeof(tem));}
}T,Size;
ll ans[N];
vector<int>del[N]; int main() {
n=Get(),m=Get(),p1=Get(),p2=Get();
for(int i=1;i<=n;i++) a[i]=Get();
pre(); for(int i=1;i<=m;i++) q[i].l=Get(),q[i].r=Get(),q[i].id=i;
for(int i=1;i<=m;i++) {
ans[q[i].id]+=(q[i].r-q[i].l)*p1;
} sort(q+1,q+1+m,cmpl);
for(int i=1;i<=n;i++) del[L[i]-1].push_back(R[i]+1);
for(int i=1;i<=n;i++) T.add(R[i]+1,1); int tag=0;
for(int i=1;i<=m;i++) {
while(tag<q[i].l) {
while(del[tag].size()) {
T.add(del[tag].back(),-1);
del[tag].pop_back();
}
tag++;
}
ans[q[i].id]+=T.ask(q[i].r)*p1;
}
for(int i=1;i<=n+1;i++) del[i].clear();
T.Init(); tag=1;
for(int i=1;i<=n;i++) del[R[i]].push_back(i);
sort(q+1,q+1+m,cmpR);
for(int i=1;i<=m;i++) {
while(tag<=q[i].r) {
T.add(n-L[tag]+2,-tag);
Size.add(n-L[tag]+2,1);
while(del[tag].size()) {
int x=del[tag].back();
T.add(n-L[x]+2,x);
Size.add(n-L[x]+2,-1);
T.add(n-L[x]+2,R[x]-x);
del[tag].pop_back();
}
tag++;
}
ans[q[i].id]+=p2*(Size.ask(n-q[i].l+1)*q[i].r+T.ask(n-q[i].l+1));
} for(int i=0;i<=n+1;i++) del[i].clear();
T.Init(),Size.Init();
sort(q+1,q+1+m,cmpL);
tag=n;
for(int i=1;i<=n;i++) del[L[i]].push_back(i);
for(int i=1;i<=m;i++) {
while(tag>=q[i].l) {
T.add(R[tag]+1,tag);
Size.add(R[tag]+1,1);
while(del[tag].size()) {
int x=del[tag].back();
T.add(R[x]+1,-x);
Size.add(R[x]+1,-1);
T.add(R[x]+1,x-L[x]);
del[tag].pop_back();
}
tag--;
}
ans[q[i].id]+=p2*(T.ask(q[i].r)-Size.ask(q[i].r)*q[i].l);
}
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n"; return 0;
}

「AHOI / HNOI2017」影魔的更多相关文章

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

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

  2. loj#2020 「AHOI / HNOI2017」礼物 ntt

    loj#2020 「AHOI / HNOI2017」礼物 链接 bzoj没\(letex\),差评 loj luogu 思路 最小化\(\sum\limits_1^n(a_i-b_i)^2\) 设改变 ...

  3. 「AHOI / HNOI2017」单旋

    「AHOI / HNOI2017」单旋 题目链接 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种 ...

  4. loj #2023. 「AHOI / HNOI2017」抛硬币

    #2023. 「AHOI / HNOI2017」抛硬币   题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个 ...

  5. loj #2021. 「AHOI / HNOI2017」大佬

    #2021. 「AHOI / HNOI2017」大佬   题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢 ...

  6. [LOJ 2022]「AHOI / HNOI2017」队长快跑

    [LOJ 2022]「AHOI / HNOI2017」队长快跑 链接 链接 题解 不难看出,除了影响到起点和终点的射线以外,射线的角度没有意义,因为如果一定要从该射线的射出一侧过去,必然会撞到射线 因 ...

  7. 「AHOI / HNOI2017」礼物

    「AHOI / HNOI2017」礼物 题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰 ...

  8. loj#2020. 「AHOI / HNOI2017」礼物

    题意:给定xy数组求 \(\sum_{i=0}^{n-1}(x_i+y_{(i+k)\modn}+c)^2\) 题解:先化简可得 \(n*c^2+2*\sum_{i=0}^{n-1}x_i-y_i+\ ...

  9. Loj #2495. 「AHOI / HNOI2018」转盘

    Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...

随机推荐

  1. python进程池

    当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiproce ...

  2. H5新增特性、方法

    1.FileReader和progress实现实时监控文件上传进度 2.HTML5新增的客户端校验 1.调用checkValidity方法进行校验 2.setCustomValidity自定义错误

  3. Django-Oscar小记:如何使用高版本Django开发网页的SEO模块

    在使用Google搜索Django的SEO插件时,很多插件都没有更新到Python3.x,有的插件更新到了Python的高版本,但是不适用于Django的2.x. Django在升级到版本2.x的时候 ...

  4. jQuery 练习:取出数组字典的值, 静态对话框, clone方法应用

    jQuery 中文API文档 http://jquery.cuishifeng.cn/ jQuery 取出数组字典的值 <head> <meta charset="UTF- ...

  5. Django之URL路由系统

    一 URL配置 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表.你就是以这 ...

  6. docker swarm 集群进入某节点容器失败的原因及解决方法

    今日在自己的docker swarm 测试环境中,想进入某个节点的容器去查看下,结果进入容器失败,并且报了如下错误信息: [root@worker1 ~]# docker exec -it 9a6f6 ...

  7. Loadrunner 脚本开发-利用loadrunner开发Windows Sockets协议脚本

    脚本开发-利用loadrunner开发Windows Sockets协议脚本 by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 实践举例 Socket服务端简单实 ...

  8. Stable Fur Generation on Mesh

    After tested the Maya 2015 XGen Grooming, we dropped it, that's really slow and unstable, totally no ...

  9. Android IPC机制(三)使用AIDL实现跨进程方法调用

    上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...

  10. 全方位理解Android权限之底层实现概览

    0000 这个阶段搞了很多和Android文件权限相关的问题,虽然一知半解,但也算是对Android权限机制有一些自己的理解.遂将这些内容整理出来.因为权限这部分涉及到的内容很多,故将知识分为几块内容 ...