题解 CF997E 【Good Subsegments】
先将问题进行转化,发现满足\((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】的更多相关文章
- [cf997E]Good Subsegments
		一个区间为好区间当且仅当$\max_{l\le i\le r}a_{i}-\min_{l\le i\le r}a_{i}=r-l$,考虑固定右端点$r$,维护所有左端点$l$的上述式子左-右的值,那么 ... 
- 「CF997E」 Good Subsegments
		CF997E Good Subsegments 传送门 和 CF526F 差不多,只不过这道题是对多个子区间进行询问. 据说有一个叫析合树的东西可以在线做,不过有时间再说吧. 考虑离线询问,将每个询问 ... 
- CF 997E 解题报告
		CF997E Good Subsegments 给你一个长度为\(n\)的排列 \(P\),定义一段子区间是好的,当且仅当这个子区间内的值构成了连续的一段.例如对于排列\(\{1,3,2\}\),\( ... 
- 【CF997E】Good Subsegments (线段树+单调栈)
		Description 原题链接 给你一个长度为\(n\)的排列\(~P\),定义一段子区间是好的,当且仅当这个子区间内的值构成了连续的一段.例如对于排列\(\{1,3,2 \}\),\([1, 1] ... 
- 【Codeforces Round】 #431 (Div. 2) 题解
		Codeforces Round #431 (Div. 2) A. Odds and Ends time limit per test 1 second memory limit per test ... 
- CoderForces Round60-(1117A,1117B,1117C题解)
		A. Best Subsegment time limit per test 1 second memory limit per test 256 megabytes input standard i ... 
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
		我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ... 
- noip2016十连测题解
		以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ... 
- BZOJ-2561-最小生成树 题解(最小割)
		2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ... 
随机推荐
- OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)
			若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ... 
- 用Creator实现一个擀面的效果
			先上几张效果图 怎么实现的呢? 节点介绍 1是背景图,可以忽略:2 是准备好的面团:3 是擀好的面饼先隐藏:4 是需要绘制的节点:5 是擀面杖. 制作开始 首先在view上挂一个mask,并且设置为模 ... 
- 【Spring】内嵌Tomcat&去Xml&调试Mvc
			菜瓜:今天听到个名词“父子容器”,百度了一下,感觉概念有点空洞,这是什么核武器? 水稻:你说的是SpringMvc和Spring吧,其实只是一个概念而已,用来将两个容器做隔离,起到解耦的作用,其中子容 ... 
- 序列推荐(transformer)
			目录 Attention演进(RNN&LSTM&GRU&Seq2Seq + Attention机制) LSTM GRU Seq2Seq + Attention机制 Attent ... 
- autocomplete 之 ASP.NET
			<link href="CSS/jquery.autocomplete.css" rel="stylesheet" type="text/css ... 
- Unity ugui Anchor锚点自动适配画布中的相对位置
			本随笔参考了以下博客,在此基础上进行优化和改进: https://blog.csdn.net/qq_39640124/article/details/88284191 ugui中的Anchor预设如下 ... 
- hive中标准偏差函数stddev()详细讲解
			1.标准偏差概念 标准偏差(Std Dev,Standard Deviation) -统计学名词.一种度量数据分布的分散程度之标准,用以衡量数据值偏离算术平均值的程度.标准偏差越小,这些值偏离平均值就 ... 
- 大型Java进阶专题(六)设计模式之代理模式
			代理模式 前言 又开始我的专题了,又停滞了一段时间了,加油继续吧.都知道 SpringAOP 是用代理模式实现,到底是怎么实现的?我们来一探究竟,并且自己仿真手写还原部分细节. 代理模式的应用 在生活 ... 
- List AND Set
			第二章 List集合 Collection中的常用几个子类(java.util.List集合.java.util.Set集合). 1.1 List接口介绍 java.util.List接口继承自Col ... 
- Spring Cloud Alibaba系列(六)sentinel的实际应用
			一.sentinel的持久化配置 上一章中我们通过Dashboard来为Sentinel客户端设置各种各样的规则,但是这些规则默认是存放在内存中,极不稳定,无法用于生成环境,所以需要将其持久化. Da ... 
