[AH2017/HNOI2017]影魔

30pts

暴力在每个区间中枚举点对(a,b)(a,b)(a,b)并查询点对之间的最大值maxmaxmax,若max&lt;=min(a,b)max&lt;=min(a,b)max<=min(a,b)则贡献p1p1p1,若min(a,b)&lt;max&lt;max(a,b)min(a,b)&lt;max&lt;max(a,b)min(a,b)<max<max(a,b)则贡p2p2p2

60pts的tip

这个p1=2∗p2p1=2*p2p1=2∗p2提醒我们什么事情?当我们查询到maxmaxmax时,我们做了一个判断,若a,ba,ba,b中有两个数大于maxmaxmax则贡献p1p1p1,若只有一个数大于maxmaxmax就贡献p2p2p2,所以我们发现这两种情况其实是有关联的。于是我们又发现了一件事情,我们对于每一对(a,b)(a,b)(a,b),只关心其中的maxmaxmax,并不关心其他数,所以我们考虑枚举中间那个maxmaxmax,然后找到maxmaxmax左/右边比他大的第一个位置l[i]/r[i]l[i]/r[i]l[i]/r[i],那么就有以下三种情况:
1,区间[l[i],r[i]−1],[l[i],r[i]−2],...,[l[i],i+1][l[i],r[i]-1],[l[i],r[i]-2],...,[l[i],i+1][l[i],r[i]−1],[l[i],r[i]−2],...,[l[i],i+1]这些区间都能贡献p2p2p2
2,区间[l[i]+1,r[i]],[l[i]+2,r[i]],...,[i−1,r[i]][l[i]+1,r[i]],[l[i]+2,r[i]],...,[i-1,r[i]][l[i]+1,r[i]],[l[i]+2,r[i]],...,[i−1,r[i]]这些区间都能贡献p2p2p2
3,区间[l[i],r[i]][l[i],r[i]][l[i],r[i]]可以贡献一个p1p1p1

其实到这里只剩复杂度优化的问题了

100pts

离线处理,对于上述三种情况有以下:
1,这一类区间左端点固定,将询问按照左端点排序,从右往左扫,如果遇到一个l[i]l[i]l[i]就在线段树上把区间[i+1,r[i]−1][i+1,r[i]-1][i+1,r[i]−1]全部加上p2p2p2,如果遇到一个询问的左端点L,就在线段树上查询[L,R][L,R][L,R]的和
2,几乎同上,反着做一遍
3,两边扫都可以,在线段树上可以包含贡献区间的位置区间加上,扫的过程中单点查询即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+5;
int n,m,a[N],l[N],r[N];
ll t[N<<2],tag[N<<2],p1,p2;
stack <int> Q;
struct query
{int l,r,id;ll ans;
}q[N];
struct data
{int pos,l,r;
}f[N];
bool cmpa(const data x,const data y)
{return x.l<y.l;
}
bool cmpb(const data x,const data y)
{return x.r<y.r;
}
bool cmp1(const query x,const query y)
{return x.l<y.l;
}
bool cmp2(const query x,const query y)
{return x.r<y.r;
}bool cmp3(const query x,const query y)
{return x.id<y.id;
}
int read()
{int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
int Read()
{ll x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
void Get_lr()
{a[0]=a[n+1]=n+1;while (Q.size()) Q.pop();Q.push(0);for (int i=1;i<=n;i++){while (Q.size()&&a[i]>a[Q.top()]) Q.pop();l[i]=Q.top();Q.push(i);}while (Q.size()) Q.pop();Q.push(n+1);for (int i=n;i>=1;i--){while (Q.size()&&a[i]>a[Q.top()]) Q.pop();r[i]=Q.top();Q.push(i);}for (int i=1;i<=n;i++) f[i]=(data){i,l[i],r[i]};return;
}
void Pushdown(int p,int ls,int rs,int l,int r)
{if (!tag[p]) return;int mid=(l+r)>>1;tag[ls]+=tag[p];tag[rs]+=tag[p];t[ls]+=tag[p]*(mid-l+1);t[rs]+=tag[p]*(r-(mid+1)+1);tag[p]=0;return;
}
void Modify(int p,int l,int r,int L,int R,ll v)
{if (L<=l&&r<=R){t[p]+=v*(r-l+1);tag[p]+=v;return;}int ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;Pushdown(p,ls,rs,l,r);if (L<=mid) Modify(ls,l,mid,L,R,v);if (R>mid) Modify(rs,mid+1,r,L,R,v);t[p]=t[ls]+t[rs];return;
}
ll Query(int p,int l,int r,int L,int R)
{if (L<=l&&r<=R) return t[p];ll ret=0;int ls=p<<1,rs=p<<1|1,mid=(l+r)>>1;Pushdown(p,ls,rs,l,r);if (L<=mid) ret+=Query(ls,l,mid,L,R);if (R>mid) ret+=Query(rs,mid+1,r,L,R);t[p]=t[ls]+t[rs];return ret;
}
int Find1(int val)
{int l=1,r=n,mid;while (l<r){mid=(l+r)>>1;if (f[mid].l>=val) r=mid;else l=mid+1;}return l;
}
int Find2(int val)
{int l=1,r=n,mid;while (l<r){mid=(l+r+1)>>1;if (f[mid].r<=val) l=mid;else r=mid-1;}return l;
}
void Solve()
{//case 1memset(t,0,sizeof(t));memset(tag,0,sizeof(tag));sort(q+1,q+m+1,cmp1);sort(f+1,f+n+1,cmpa);int now=n+1;for (int i=m;i>=1;i--){int tmp;tmp=Find1(q[i].l);for (int j=now-1;j>=tmp;j--) if (f[j].pos+1<=f[j].r-1) Modify(1,0,n+1,f[j].pos+1,f[j].r-1,p2);now=tmp;q[i].ans+=Query(1,0,n+1,q[i].l,q[i].r);}//case 2memset(t,0,sizeof(t));memset(tag,0,sizeof(tag));sort(q+1,q+m+1,cmp2);sort(f+1,f+n+1,cmpb);now=0;for (int i=1;i<=m;i++){int tmp;tmp=Find2(q[i].r);for (int j=now+1;j<=tmp;j++) if (f[j].l+1<=f[j].pos-1) Modify(1,0,n+1,f[j].l+1,f[j].pos-1,p2);now=tmp;q[i].ans+=Query(1,0,n+1,q[i].l,q[i].r);}//case 3memset(t,0,sizeof(t));memset(tag,0,sizeof(tag));sort(q+1,q+m+1,cmp2);sort(f+1,f+n+1,cmpb);now=0;for (int i=1;i<=m;i++){int tmp;tmp=Find2(q[i].r);for (int j=now+1;j<=tmp;j++)if (1<=f[j].l) Modify(1,0,n+1,1,f[j].l,p1);now=tmp;q[i].ans+=Query(1,0,n+1,q[i].l,q[i].l);}return;
}
int main()
{n=read(),m=read(),p1=Read(),p2=Read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;Get_lr();Solve();sort(q+1,q+m+1,cmp3);for (int i=1;i<=m;i++) q[i].ans+=(q[i].r-q[i].l)*p1,printf("%lld\n",q[i].ans);return 0;
}

[AH2017/HNOI2017] 影魔相关推荐

  1. [AH2017/HNOI2017]影魔

    P3722 [AH2017/HNOI2017]影魔 题解: 法一: [bzoj4826][HNOI2017]影魔 直接转化成区间内单点的贡献, 分开p1,p2考虑 而min(ai,aj),max(ai ...

  2. P3722 [AH2017/HNOI2017]影魔(树状数组)

    题目描述 奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n.第 i 个灵魂的战斗力为 ki ,灵魂们以点对的形式为影魔提供攻击力.对于灵魂对 i,j (i<j) ...

  3. 洛谷P3722 [AH2017/HNOI2017]影魔

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

  4. [AH2017/HNOI2017]影魔(主席树+单调栈)

    设\(l[i]\)为i左边第一个比i大的数的下标.\(r[i]\)为i右边第一个比i大的数的下标. 我们把\(p1,p2\)分开考虑. 当产生贡献为\(p1\)时\(i\)和\(j\)一定满足,分别为 ...

  5. (每日一题)P3723 [AH2017/HNOI2017]礼物(经典FFT)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 每日一题(莫反 / 多项式 / 母函数 / 群论) 2021.4.15 多项式 FFT Problem ...

  6. P3723 [AH2017/HNOI2017]礼物(FFT)

    P3723 [AH2017/HNOI2017]礼物 式子化简 ∑i=1n(xi−yj)2\sum_{i = 1} ^{n} (x_i- y_j) ^2\\ i=1∑n​(xi​−yj​)2 我们对第一 ...

  7. P3723 [AH2017/HNOI2017]礼物 FFT + 式子化简

    传送门 文章目录 题意: 思路: 题意: 思路: 首先可以知道,我们对某个数组加上一个正数数的操作可以转换成对一个数组加上一个任意数,所以我们设变化量为xxx. 对于∑i=1n(ai−bi)2\sum ...

  8. 【BZOJ4826】[Hnoi2017]影魔 单调栈+扫描线

    [BZOJ4826][Hnoi2017]影魔 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝 ...

  9. AH2017/HNOI2017 礼物

    P3723 [AH2017/HNOI2017]礼物 题目大意 给两个数列 a a a和 b b b, a a a和 b b b中的数都小于等于 m m m, b b b可以首尾相接地旋转,要选择一个整 ...

最新文章

  1. 教你如何实现c#文件上传下载功能
  2. chmod 4755和chmod 755的区别
  3. python语言入门u-[学习总结] python语言学习总结 (一)
  4. python适用场景_你真的了解Python吗?什么场景使用多线程,什么场景使用多进程?...
  5. 利用Scala特征(trait)的堆叠操作特性进行切面编程
  6. c语言有趣代码_【新课预知】——C语言程序设计
  7. HDU5763 Another Meaning(KMP+dp)
  8. linux设置默认终端模拟器,ubuntu终端默认设置_在Ubuntu Linux上设置默认终端模拟器...
  9. Linux学习笔记---初次编译Uboot系统
  10. 【网络爬虫入门01】应用Requests和BeautifulSoup联手打造的第一条网络爬虫
  11. 你的主机中的软件中止了一个已建立的连接
  12. 武汉加油!爬取百度迁徙地图数据+城市出行强度
  13. Java软件开发修炼过程
  14. 根据经纬度求距离(算法)
  15. Python搭建QQ机器人,监控QQ发言与进群退群,自动@新成员并屏蔽脏话踢人
  16. Java实现Word转PDF【完整版】
  17. 万事开头难 实践出真知
  18. PHP版本更新功能实现,技术分享:最低PHP版本更新操作 | Wopus
  19. 使用AWS最便宜的GPU实例  from 动手学深度学习v2 李沐大神
  20. python爬取B站网页排行榜数据(进阶版)

热门文章

  1. 广州市海珠区2021-2022学年七年级第一学期期末考试英语试题
  2. 如何撰写产品需求文档_需求文档模板(产品功能类需求篇)
  3. 利用 imu_utils 标定 imu
  4. Go语言特性记录及与java、python对比之包、变量和函数
  5. Flutter应用使用插件报错问题
  6. 大电流场效应管500a_常用大功率场效应管参数
  7. L*MM 文件管理器小结
  8. n的阶乘三种实现方法(C语言)
  9. 解决《空中英语教室》Super MP3光盘繁体字乱码的方法
  10. RacerX Effective, Static Detection of Race Conditions and Deadlocks调研笔记