https://www.lydsy.com/JudgeOnline/problem.php?id=4826

年少不知空间贵,相顾mle空流泪。

和上一道主席树求的东西差不多,求两种对

1. max(a[(i,j)])<min(a[i],a[j]),[i,j]这一对贡献p1.

2. max(a[(i,j)])在a[i],a[j]之间,[i,j]这一对贡献p2.

第一种和bzoj3956那道一样,但是因为是排列所以没必要去重了。

第二种同样是单调栈求lp,rp,每个位置的lp分别和[ i+1 , rp-1 ], rp分别和[ lp+1 , i-1 ], 构成了贡献p2的数对。

因此贡献为p2的数对要区间修改,因为方便(不用downdata)(其实是因为我抄的代码就是标记永久化)所以写了标记永久化,标记永久化真的挺好用的嘻嘻。

感觉写了这道题终于有点摸到主席树的门路了,其实就是找和维护两个区间进行限制的值(找和维护一个二维块),一层线段树一层前缀和(只是有传递性不一定是实际意义的和)。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define LL long long
 8 const int maxn=200010;
 9 LL n,m,p1,p2;
10 LL a[maxn]={},sta[maxn]={},tail=0;
11 LL lp[maxn]={},rp[maxn]={},rt[maxn]={};
12 LL lc[maxn*64]={},rc[maxn*64]={},siz[maxn*64]={},ad[maxn*64]={},tot=0;
13 struct nod{
14     LL x,l,r,v;
15 }e[maxn*4];
16 LL cnt=0;
17 bool mcmp(nod aa,nod bb){ return aa.x<bb.x; }
18 LL read(){
19     LL w=0,f=1;char ch=getchar();
20     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
21     while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
22     return w*f;
23 }
24 void build(LL &x,LL y,LL l,LL r,LL z,LL zl,LL zr){
25     x=++tot;lc[x]=lc[y];rc[x]=rc[y];ad[x]=ad[y];siz[x]=siz[y]+z*(zr-zl+1);
26     if(zl==l&&r==zr){ad[x]+=z;return;}
27     LL mid=(l+r)/2;
28     if(zr<=mid)build(lc[x],lc[y],l,mid,z,zl,zr);
29     else if(zl>mid) build(rc[x],rc[y],mid+1,r,z,zl,zr);
30     else {
31         build(lc[x],lc[y],l,mid,z,zl,mid);
32         build(rc[x],rc[y],mid+1,r,z,mid+1,zr);
33     }
34 }
35 LL getsum(LL x,LL y,LL l,LL r,LL zl,LL zr){
36     if(zl==l&&r==zr)return siz[y]-siz[x];
37     LL mid=(l+r)/2,ans=(ad[y]-ad[x])*(zr-zl+1);
38     if(zr<=mid)return ans+getsum(lc[x],lc[y],l,mid,zl,zr);
39     else if(zl>mid) return ans+getsum(rc[x],rc[y],mid+1,r,zl,zr);
40     else {
41         return ans+getsum(lc[x],lc[y],l,mid,zl,mid)+getsum(rc[x],rc[y],mid+1,r,mid+1,zr);
42     }
43 }
44 //以上主席树
45 inline void fir(){
46     LL i;
47     a[0]=a[n+1]=(1<<30);
48     for(i=1;i<=n;++i){
49         while(a[sta[tail]]<=a[i])tail--;
50         lp[i]=sta[tail];sta[++tail]=i;
51     }
52     sta[0]=n+1;tail=0;
53     for(i=n;i>0;--i){
54         while(a[sta[tail]]<=a[i])tail--;
55         rp[i]=sta[tail];sta[++tail]=i;
56     }
57 }
58 inline void init(LL x,LL l,LL r,LL v){
59     e[++cnt].x=x;e[cnt].l=l;e[cnt].r=r;e[cnt].v=v;
60 }
61 inline void fir2(){
62     LL i,j;
63     for(i=1;i<=n;++i){
64         if(lp[i]!=0&&rp[i]!=n+1)init(lp[i],rp[i],rp[i],p1);
65         if(i<n)init(i,i+1,i+1,p1);
66         if(lp[i]!=0&&rp[i]-i>1)init(lp[i],i+1,rp[i]-1,p2);
67         if(rp[i]!=n+1&&i-lp[i]>1)init(rp[i],lp[i]+1,i-1,p2);
68     }
69     sort(e+1,e+cnt+1,mcmp);
70     for(i=j=1;i<=n;++i){
71         rt[i]=rt[i-1];
72         for(;e[j].x==i&&j<=cnt;++j)build(rt[i],rt[i],1,n,e[j].v,e[j].l,e[j].r);
73     }
74 }
75 int main(){
76     LL i,x,y,ans=0;
77     n=read();m=read();p1=read();p2=read();
78     for(i=1;i<=n;++i)a[i]=read();
79     fir(); fir2();
80     for(i=1;i<=m;++i){
81         x=read();y=read();
82         if(x>y)swap(x,y);
83         ans=getsum(rt[x-1],rt[y],1,n,x,y);
84         printf("%lld\n",ans);
85     }
86     return 0;
87 }

View Code

转载于:https://www.cnblogs.com/137shoebills/p/8794916.html

BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树相关推荐

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

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

  2. bzoj 4826: [Hnoi2017]影魔

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

  3. bzoj 4826 [Hnoi2017]影魔

    http://www.elijahqi.win/archives/3687 Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式 ...

  4. [CF 526 F] Pudding Monsters(单调栈 + 线段树)

    CF526F Pudding Monsters problem solution code problem luogu翻译 solution observation :每行每列恰好有一个棋子,所以如果 ...

  5. 【BZOJ】3956 Count 单调栈+ST表

    题目传送门 挺有思想的一题,但如果弄清楚了思路这题还是挺简单的. 首先我们可以发挥一下自己的脑洞,发现所有的好集对不可能相交. 那么我们可以刷两遍单调栈,求出每个点作为区间左端点或右端点的次数. 对于 ...

  6. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  7. HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑将贡献分开来算,先计算最大值,再算个最小值,之后答案就是((max+min)/2)/(len∗(len+1)/2)((max+min)/2)/(l ...

  8. [LOJ3153] 三级跳(单调栈 + 线段树)

    problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论: 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对,如果有一个数 i∈(x,y)∧ai≥axi ...

  9. 扶桑号战列舰【单调栈+线段树】

    扶桑号战列舰 传送门  来源upc:12800 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当 ...

最新文章

  1. IntelliTest(5) - The IntelliTest Reference Manual[译]
  2. 分享一下dudu回答的一个方法
  3. MFCButton Memory leak(内存泄露问题)
  4. c#app.config配置文件使用
  5. java 队列总结queue v3 svv.docxjava 队列总结queue v3 svv.docx atitit. java queue 队列体系总结o7t 1. 队列概念 1 1.1. 队列
  6. 【车间调度】基于matlab模拟退火算法求解车间调度问题【含Matlab源码 894期】
  7. .net mvc html.row,ASP.NET MVC4中的WebGrid
  8. 微信小程序选项卡页面切换
  9. cloud2声卡_带你解惑HyperX Cloud2(飓风)和Alpha(阿尔法)的终极选择
  10. 高通蓝牙耳机开发方法-周康
  11. 在自己本地原有的镜像基础上用dockerfile加一下库进去
  12. 鼠标自动点击工具鼠标连点器鼠标定时自动点击使用方法
  13. 沃商店运营一周年凸显平台化优势
  14. 099node-MongoDB数据库添加账户
  15. 洛谷P1460 健康的荷斯坦奶牛
  16. 人——Web3的新平台
  17. Homekit智能家居DIY设备一智能灯泡
  18. uniapp 二维码展示和扫码
  19. 游戏抽奖界面html,基于JavaScript实现幸运抽奖页面
  20. go swag常用注释

热门文章

  1. python 调用 C++ code
  2. MDT2012+ADK8.0+WDS部署Windows客户端(一)部署概念和方法论
  3. L1-074 两小时学完C语言 (5 分)-PAT 团体程序设计天梯赛 GPLT
  4. PAT 乙级 1001. 害死人不偿命的(3n+1)猜想 (15) Java版
  5. LeetCode 454. 4Sum II
  6. 外点罚函数matlab程序_关于图像轮廓识别的程序实现
  7. python通过SNMP协议收集服务器监控信息(安装、配置、示例)
  8. Spring Cloud Zuul--服务网关
  9. 并发 --- 32 管道 事件 信号量 进程池
  10. MYSQL存储过程中事务和DECLARE EXIT/CONTINUE HANDLER的使用