(这是石神找到的一道hiao题。)

题意:

你有一个长度为n的排列,有Q组询问$[l,r]$,每次询问$[l,r]$的子区间中有多少是好的。

一个区间是好的区间当且仅当该区间中的元素在排序后是连续的。

$n,Q\leq 120000$。

题解:

为什么说这是一道hiao题呢?

像我一样的数据结构弱智选手看到之后可能会想一些树套树的操作。

但这个题有一种具有代表性的经典方法。

注意到一段区间是好的当且仅当$(max-min)-(r-l)=0$。

我们可以将将询问离线下来,每次处理以$r$为右端点的所有询问。

考虑从左往右枚举右端点$r$,并用一棵线段树维护每个点$l$的$(max-min)-(r-l)$的值。

我们不妨将以$r$为右端点时的这颗线段树称作版本$r$。

那么,以$r$为右端点的好区间个数就是版本$r$中0的个数。

以$r$为右端点,左端点在$[l,r]$间的好区间个数就是版本$r$中$[l,r]$中0的个数之和,记为$siz[r][l,r]$。

但是注意到,我们要求的答案其实是$\sum_{i=l}^{r}{siz[i][l,i]}$。

那么需要对线段树上的每个节点额外记录一个$sum$,代表这个区间所有版本中0的个数之和。

也就是${sum[l,r]}=\sum_{i=1}^{now}{siz[i][l,r]}$。

显然答案就是$sum[l,r]$,那么如何维护这个$sum$呢?

不妨维护一个类似$lazy$标记的$tag$标记,表示该区间现在的$siz$要对$sum$产生几次的贡献。

这个标记实际上就是把$min=0$时的$siz$一直继承下来,直到访问到它的时候再更新$siz$。

注意无论该区间现在的$min$值是不是等于0(可能被上面区间的$pushdown$改掉了),在访问到它之前都需要保留该标记,因为那个0的版本始终是有贡献的。

在$pushdown$这个$tag$的时候要注意:假如该区间当前的$min$值是由一个而不是两个子区间转移上来的,那我们只应该更新转移上来的那个子区间的$tag$。

如何判断哪个是转移上来的子区间?显然当且仅当$min_{son}=min_{now}$(注意$min_{now}$未必等于0)。

时间复杂度$O((n+Q)logn)$。

积累套路:对于询问区间子序列的信息,可以离线移动右指针,类似扫描线一样计算贡献。

代码:

#include<bits/stdc++.h>
#define maxn 120005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long using namespace std;
ll N,Q,A[maxn],mn[maxn<<],ans[maxn];
ll sum[maxn<<],nd[maxn<<],lz[maxn<<];
ll siz[maxn<<],tim[maxn<<];
vector<pair<ll,ll> > ques[maxn];
struct node{ll v,l,r;};
stack<node> smx,smn; inline ll read(){
ll x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
} inline void pushup(ll k){
if(mn[k<<]==mn[k<<|]) mn[k]=mn[k<<],siz[k]=siz[k<<]+siz[k<<|];
else if(mn[k<<]<mn[k<<|]) mn[k]=mn[k<<],siz[k]=siz[k<<];
else mn[k]=mn[k<<|],siz[k]=siz[k<<|];
}
inline void pushdown(ll k){
if(lz[k]){
lz[k<<]+=lz[k],lz[k<<|]+=lz[k];
mn[k<<]+=lz[k],mn[k<<|]+=lz[k];
lz[k]=;
}
if(nd[k]){
if(mn[k<<]==mn[k]) sum[k<<]+=siz[k<<]*nd[k],nd[k<<]+=nd[k];
if(mn[k<<|]==mn[k]) sum[k<<|]+=siz[k<<|]*nd[k],nd[k<<|]+=nd[k];
nd[k]=;
}
}
inline void build(ll l,ll r,ll k){
if(l==r){mn[k]=inf,siz[k]=;return;}
ll mid=l+r>>;
build(l,mid,k<<),build(mid+,r,k<<|);
pushup(k); return;
}
inline void add(ll l,ll r,ll x,ll y,ll v,ll t,ll k){
if(x<=l && r<=y){mn[k]+=v,lz[k]+=v;return;}
pushdown(k); ll mid=l+r>>;
if(x<=mid) add(l,mid,x,y,v,t,k<<);
if(y>mid) add(mid+,r,x,y,v,t,k<<|);
pushup(k); return;
}
inline void ins(ll l,ll r,ll p,ll v,ll t,ll k){
if(l==r){mn[k]=v;return;}
pushdown(k); ll mid=l+r>>;
if(p<=mid) ins(l,mid,p,v,t,k<<);
else ins(mid+,r,p,v,t,k<<|);
pushup(k); return;
}
inline ll query(ll l,ll r,ll x,ll y,ll t,ll k){
if(x<=l && r<=y) return sum[k];
pushdown(k); ll mid=l+r>>,res=;
if(x<=mid) res+=query(l,mid,x,y,t,k<<);
if(y>mid) res+=query(mid+,r,x,y,t,k<<|);
return res;
} int main(){
N=read();
for(ll i=;i<=N;i++) A[i]=read();
Q=read();
for(ll i=;i<=Q;i++){
ll l=read(),r=read();
ques[r].push_back(make_pair(i,l));
}
build(,N,);
for(ll i=;i<=N;i++){
ll x=A[i],nl1=i,nl2=i;
while(!smx.empty()){
if(smx.top().v<x){
ll l=smx.top().l,r=smx.top().r;
add(,N,l,r,x-smx.top().v,i,);
nl1=l,smx.pop();
}
else break;
}
while(!smn.empty()){
if(smn.top().v>x){
ll l=smn.top().l,r=smn.top().r;
add(,N,l,r,smn.top().v-x,i,);
nl2=l,smn.pop();
}
else break;
}
node tp1; tp1.v=x,tp1.l=nl1,tp1.r=i;
node tp2; tp2.v=x,tp2.l=nl2,tp2.r=i;
smx.push(tp1),smn.push(tp2);
if(i-) add(,N,,i-,-,i,);
ins(,N,i,,i,);
sum[]+=siz[],nd[]+=;
for(ll j=;j<ques[i].size();j++){
ll l=ques[i][j].second,r=i,id=ques[i][j].first;
ans[id]=query(,N,l,r,i,);
}
}
for(ll i=;i<=Q;i++)
printf("%I64d\n",ans[i]);
return ;
}

cf 997 E

[cf 997 E] Good Subsegments的更多相关文章

  1. #C++初学记录(set进阶#acm cf 190802 B. Subsegments)

    B. Subsegments#set进阶 Programmer Sasha has recently begun to study data structures. His coach Stas to ...

  2. CF 372B Counting Rectangles is Fun [dp+数据维护]

    题意,给出一个n行m列的矩阵 里面元素是0或者1 给出q个询问 a,b,c,d 求(a,b)到(c,d)有多少个由0组成的矩形 我们定义 watermark/2/text/aHR0cDovL2Jsb2 ...

  3. ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'

    凌晨收到同事电话,反馈应用程序访问Oracle数据库时报错,当时现场现象确认: 1. 应用程序访问不了数据库,使用SQL Developer测试发现访问不了数据库.报ORA-12570 TNS:pac ...

  4. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

  5. cf Round 613

    A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个 ...

  6. ARC下OC对象和CF对象之间的桥接(bridge)

    在开发iOS应用程序时我们有时会用到Core Foundation对象简称CF,例如Core Graphics.Core Text,并且我们可能需要将CF对象和OC对象进行互相转化,我们知道,ARC环 ...

  7. [Recommendation System] 推荐系统之协同过滤(CF)算法详解和实现

    1 集体智慧和协同过滤 1.1 什么是集体智慧(社会计算)? 集体智慧 (Collective Intelligence) 并不是 Web2.0 时代特有的,只是在 Web2.0 时代,大家在 Web ...

  8. CF memsql Start[c]UP 2.0 A

    CF memsql Start[c]UP 2.0 A A. Golden System time limit per test 1 second memory limit per test 256 m ...

  9. CF memsql Start[c]UP 2.0 B

    CF memsql Start[c]UP 2.0 B B. Distributed Join time limit per test 1 second memory limit per test 25 ...

随机推荐

  1. uni-app 网络请求

    uni.request发起网络请求 url 开发者服务器接口地址 data 请求的参数 header method dataType responseType 设置响应的数据类型 statusCode ...

  2. eclipseWeb项目如何实现网址发送给外人——内部穿透

    教程:https://blog.csdn.net/Feihongxiansen/article/details/94480480 部署完成后: 打开cmd命令: 暴露端口8081成功: 将eclips ...

  3. SpringCloud:学习Gateway网关拦截器的ServerWebExchange

    1.Gateway的拦截器 我们要在项目中实现一个拦截器,需要继承两个类:GlobalFilter, Ordered GlobalFilter:全局过滤拦截器,在gateway中已经有部分实现,具体参 ...

  4. quick: setup_mac.sh分析

    //quick: setup_mac.sh分析 //quick: setup_mac.sh分析#!/bin/bash //获取并打印根目录QUICK_V3_ROOTDIR="$( cd &q ...

  5. Fluent导出残差总结

    在使用Fluent进行求解的时候,有时候我们需要将求解的残差提取出来,进行后续的处理,我们可以采用下面的方法将Fluent求解残差输出.下面我们用一个简单的二维算例来说明(算例来源于:https:// ...

  6. zabbix-常规配置

    zabbix server:cat zabbix_server.confLogFile=/data/log/zabbix_server.logLogFileSize=250DebugLevel=3Pi ...

  7. 《微信小程序商城开发实战》笔者的新书,欢迎各位粉丝上京东购买

    作者图书京东链接,请点击------>>>    **微信小程序商城开发实战** 附京东真实评价截图: 编辑推荐 在当今移动互联网大潮中,微信应用凭借其庞大的用户基数和极强的用户黏性 ...

  8. php laravel 环境搭建

    最近上一个新项目,时间比较紧,为了满足业务需求,没有办法,只有上我大 php 了,找了一个带些基础的数据结构,用的是 laravel 搭建的,然后寻坑就开始了,先是构建 docker 镜像就坑了,然后 ...

  9. Canal - 数据同步 - 阿里巴巴 MySQL binlog 增量订阅&消费组件

    背景 早期,阿里巴巴 B2B 公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求 ,主要是基于trigger的方式获取增量变更.从 2010 年开始,公司开始逐步尝试数据库日志解析,获取增量变 ...

  10. iOS逆向(五)-ipa包重签名

    为什么要重签名? 1.在没有源代码的情况下,你已经对某个应用进行了资源修改(比如修改了启动图或图标等).修改完成以后,如果想要让APP可以正常使用,该APP一定要重新签名然后压缩成IPA文件. 2.如 ...