先将问题进行转化,发现满足\((max-min)-(r-l)=0\)的区间即为好区间。

对于本题这样的统计子区间的问题,先将询问离线,按右端点排序一个一个解决,固定右端点,然后通过数据结构来处理出区间信息,询问直接查询区间合法的贡献即可,扫一遍就能解决所有询问。

继续看这个式子\((max-min)-(r-l)=0\),发现如果去维护这个式子的值,对于固定的右端点,可以统计出其之前的左端点与该右端点的区间最小值及其个数,最小值个数即为在这个区间内可以对这个固定的右端点有贡献的左端点。

但这只能记录右端点固定的答案,无法处理子区间的问题,可以记录下历史最小值个数和,再进行询问即为这段区间的所有子区间的答案了。

具体实现时,维护\(max-min\)的变化可以通过单调栈来实现,\(r-l\)的变化直接对整个区间减一即可,历史最小值个数和需要通过打标记来看该区间是否能产生贡献,细节就看代码吧。

\(code:\)

#include<bits/stdc++.h>
#define maxn 500010
#define ls (cur<<1)
#define rs (cur<<1|1)
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,q,t1,t2,root=1;
int a[maxn],s1[maxn],s2[maxn];
ll ans[maxn],mi[maxn],cnt[maxn],sum[maxn],add[maxn],tag[maxn];
struct Query
{
int l,id;
};
vector<Query> ve[maxn];
void pushup(int cur)
{
ll lm=mi[ls],rm=mi[rs],lc=cnt[ls],rc=cnt[rs];
if(lm==rm) mi[cur]=lm,cnt[cur]=lc+rc;
if(lm<rm) mi[cur]=lm,cnt[cur]=lc;
if(lm>rm) mi[cur]=rm,cnt[cur]=rc;
sum[cur]=sum[ls]+sum[rs];
}
void pushadd(int cur,ll v)
{
mi[cur]+=v,add[cur]+=v;
}
void pushtag(int cur,ll v)
{
sum[cur]+=cnt[cur]*v,tag[cur]+=v;
}
void pushdown(int cur)
{
if(add[cur])
pushadd(ls,add[cur]),pushadd(rs,add[cur]),add[cur]=0;
if(tag[cur])
{
if(mi[cur]==mi[ls]) pushtag(ls,tag[cur]);
if(mi[cur]==mi[rs]) pushtag(rs,tag[cur]);
tag[cur]=0;
}
}
void build(int l,int r,int cur)
{
if(l==r)
{
mi[cur]=l,cnt[cur]=1;
return;
}
build(l,mid,ls),build(mid+1,r,rs);
pushup(cur);
}
void modify(int L,int R,int l,int r,ll v,int cur)
{
if(L<=l&&R>=r)
{
pushadd(cur,v);
return;
}
pushdown(cur);
if(L<=mid) modify(L,R,l,mid,v,ls);
if(R>mid) modify(L,R,mid+1,r,v,rs);
pushup(cur);
}
ll query(int L,int R,int l,int r,int cur)
{
if(L<=l&&R>=r) return sum[cur];
pushdown(cur);
ll ans=0;
if(L<=mid) ans+=query(L,R,l,mid,ls);
if(R>mid) ans+=query(L,R,mid+1,r,rs);
return ans;
}
int main()
{
read(n),build(1,n,root);
for(int i=1;i<=n;++i) read(a[i]);
read(q);
for(int i=1;i<=q;++i)
{
int l,r;
read(l),read(r);
ve[r].push_back((Query){l,i});
}
for(int i=1;i<=n;++i)
{
while(t1&&a[s1[t1]]<=a[i])
{
modify(s1[t1-1]+1,s1[t1],1,n,a[i]-a[s1[t1]],root);
t1--;
}
while(t2&&a[s2[t2]]>=a[i])
{
modify(s2[t2-1]+1,s2[t2],1,n,a[s2[t2]]-a[i],root);
t2--;
}
s1[++t1]=s2[++t2]=i,pushadd(root,-1),pushtag(root,1);
int size=ve[i].size();
for(int j=0;j<size;++j)
ans[ve[i][j].id]=query(ve[i][j].l,i,1,n,root);
}
for(int i=1;i<=q;++i) printf("%lld\n",ans[i]);
return 0;
}

题解 CF997E 【Good Subsegments】的更多相关文章

  1. [cf997E]Good Subsegments

    一个区间为好区间当且仅当$\max_{l\le i\le r}a_{i}-\min_{l\le i\le r}a_{i}=r-l$,考虑固定右端点$r$,维护所有左端点$l$的上述式子左-右的值,那么 ...

  2. 「CF997E」 Good Subsegments

    CF997E Good Subsegments 传送门 和 CF526F 差不多,只不过这道题是对多个子区间进行询问. 据说有一个叫析合树的东西可以在线做,不过有时间再说吧. 考虑离线询问,将每个询问 ...

  3. CF 997E 解题报告

    CF997E Good Subsegments 给你一个长度为\(n\)的排列 \(P\),定义一段子区间是好的,当且仅当这个子区间内的值构成了连续的一段.例如对于排列\(\{1,3,2\}\),\( ...

  4. 【CF997E】Good Subsegments (线段树+单调栈)

    Description 原题链接 给你一个长度为\(n\)的排列\(~P\),定义一段子区间是好的,当且仅当这个子区间内的值构成了连续的一段.例如对于排列\(\{1,3,2 \}\),\([1, 1] ...

  5. 【Codeforces Round】 #431 (Div. 2) 题解

    Codeforces Round #431 (Div. 2)  A. Odds and Ends time limit per test 1 second memory limit per test ...

  6. CoderForces Round60-(1117A,1117B,1117C题解)

    A. Best Subsegment time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  7. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  8. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  9. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

随机推荐

  1. Vue基础篇 (1) —— Vue-Router的使用

    Vue-Cli中Vue-Router的使用 一.创建vue-cli的项目 npm create myproject vue create 为vue.js 3.0构建项目的命令,2.0版本可以通过vue ...

  2. VC GDI+基础用法VC

    #include "GdiPlus.h" // 使用GDI+ 命名空间 using namespace Gdiplus; // 与GDI+ 相关的其它头文件,如:GraphicsP ...

  3. 前端走进机器学习生态,在 Node.js 中使用 Python

    这次给大家带来一个好东西,它的主要用途就是能让大家在 Node.js 中使用 Python 的接口和函数.可能你看到这里会好奇,会疑惑,会不解,我 Node.js 大法那么好,干嘛要用 Python ...

  4. C#实现快速查找(递归,非递归)

    原文件: http://pan.baidu.com/share/link?shareid=2838344856&uk=3912660076 我英语很烂...哎,我正在努力... 效果图:

  5. eIQ WSL下工具及环境配置

    1. 配置WSL 参考[https://www.cnblogs.com/hayley111/p/12844337.html] 2. 配置VScode 参考[https://zhuanlan.zhihu ...

  6. Python3笔记007 - 2.4 数据类型

    第2章 python语言基础 python语法特点 保留字与标识符 变量 数据类型 运算符 输入和输出 2.4 数据类型 数据类型分为:空类型.布尔类型.数字类型.字节类型.字符串类型.元组类型.列表 ...

  7. springboot集成springDataJpa

    1.引用依赖 <!--spring-data-jpa--> <dependency> <groupId>org.springframework.boot</g ...

  8. PHP实现邮箱验证码验证功能

    *文章来源:https://blog.egsec.cn/archives/623  (我的主站) *本文将主要说明:PHP实现邮箱验证码验证功能,通过注册或登录向用户发送身份确认验证码,并通过判断输入 ...

  9. meta viewport相关

    <!DOCTYPE html> H5标准声明,使用 HTML5 doctype,不区分大小写 <head lang=”en”> 标准的 lang 属性写法 <meta c ...

  10. uniapp,微信小程序中使用 MQTT

    最近在uniapp打包成微信小程序的项目中第一次用到了MQTT.使用比较简单,但是还是遇到了一些问题.在此记录一下. 官方文档:MQTT Github 官方MQTT测试工具:MQTTX.测试工具使用说 ...