题解 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 ...
随机推荐
- Java集合框架(不全,待继续整理)
技术在线学习网站: https://www.runoob.com/java/java-collections.html 从上面的集合框架图可以看到: 1.Java 集合框架主要包括两种类型的容器: 1 ...
- Python 简明教程 --- 16,Python 高阶函数
微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 对于那些快速算法,我们总是可以拿一些速度差不多但是更容易理解的算法来替代它们. -- Douglas ...
- Cannot resolve symbol window
参照官网执行如下代码的时候,报了Cannot resolve symbol window错误. val windowedCounts = words.groupBy( window($"ti ...
- JavaScript基础-自己定义自己的函数(016)
把一个函数对象赋值给变量后,就可以通过这个变量再次定义函数,甚至可以在一个函数内部再次定义它自己: var scareMe = function () { alert("Boo!" ...
- Python进阶之浅谈内置方法
目录 有序or无序和可变or不可变 数字类型内置方法 整形 浮点型 字符串类型内置方法 有序or无序和可变or不可变 有序:有索引 无序:无索引 可变:变量值变,id不变 不可变:变量值变,id也变 ...
- ES11来了,还学得动吗?
写在前面 ES2020(即 ES11)上周(2020 年 6 月)已经正式发布,在此之前进入 Stage 4 的 10 项提案均已纳入规范,成为 JavaScript 语言的新特性 一.特性一览 ES ...
- Sharepoint 编辑WebPart时,WebPart属性为灰色不可用
一般在客户端设置就是灰色的,解决方法就是,要在服务器上进行设置,就可以了.:)
- 关于位图数据和标记位-P3
文章目录 1 背景 1.1 问题 2 问题1探究 2.1 没有区的情况 2.2 一个区的情况 2.3 两个区的情况 2.4 三个区的情况 2.5 四个区的情况 2.6 五个区的情况 3 问题2探究 3 ...
- steam夏日促销悄然开始,用Python爬取排行榜上的游戏打折信息
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 不知不觉,一年一度如火如荼的steam夏日促销悄然开始了.每年通过大大小小 ...
- zookeeper3.5.5 centos7 完全分布式 搭建随记
zookeeper3.5.5 centos7 完全分布式 搭建随记 这里是当初在三个ECS节点上搭建hadoop+zookeeper+hbase+solr的主要步骤,文章内容未经过润色,请参考的同学搭 ...