首先理清这奇葩题意表述

给出一个\(1\)到\(n\)的排列\(p[]\)和\(m\)次询问,每次询问覆盖区间\([l,r]\)的最小区间\([a,b]\),满足\([a,b]\)内的元素排序后是连续整数序列。\(n,m\le 10^5,\;1\le l\le r\le n\)。

方便表述,称满足(省略)的区间是“好”的,否则是“坏”的,钦定空区间是“好”的。

罗列一些可能用到的、很显然的性质

  1. 好区间的长度等于最大值与最小值之差;
  2. 不相离的两个好区间的并是好区间;
  3. 不相离的两个好区间的交是好区间;
  4. 一个好区间内存在长度-1个值差1的无序二元组(邻数对)

我们形式化的描述性质4:设\(a[i]\)表示\(i\)到\(r\)的邻数对数,若\([l,r]\)是好区间,则\(a[l]=r-l\),或者说\(a[l]+l=r\)。令\(A[i]=a[i]+i\)考虑从左往右扫描区间右端\(r\),同时维护关于\(r\)的\(A[]\),则与\(r\)构成好区间的\(l\)满足\(A[l]=r\),显然这是\(A[]\)中最大的元素。

至此使用线段树维护区间最大值和最大值中的最大下标(好区间应将量短)即可。

#include <bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
const int N=1e5+10; int mxa[N<<2],rp[N<<2],tag[N<<2];
void update(int x) {
if(mxa[ls]==mxa[rs]) mxa[x]=mxa[ls],rp[x]=rp[rs];
else if(mxa[ls]>mxa[rs]) mxa[x]=mxa[ls],rp[x]=rp[ls];
else mxa[x]=mxa[rs],rp[x]=rp[rs];
}
void pushdown(int x) {
if(!tag[x]) return;
mxa[ls]+=tag[x],tag[ls]+=tag[x];
mxa[rs]+=tag[x],tag[rs]+=tag[x];
tag[x]=0;
}
void build(int x,int l,int r) {
if(l==r) {mxa[x]=rp[x]=l; return;}
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
update(x);
}
void modify(int x,int l,int r,int L,int R) {
if(L<=l&&r<=R) {mxa[x]++,tag[x]++; return;}
int mid=(l+r)>>1; pushdown(x);
if(L<=mid) modify(ls,l,mid,L,R);
if(mid<R) modify(rs,mid+1,r,L,R);
update(x);
}
int query(int x,int l,int r,int p,int w) {
if(mxa[x]<w) return 0;
if(r<=p) return rp[x];
int mid=(l+r)>>1; pushdown(x);
if(mid<p&&mxa[rs]>=w) {
int tmp=query(rs,mid+1,r,p,w);
if(tmp) return tmp; //似乎可以蛮会被卡称O(n)
}
return query(ls,l,mid,p,w);
} int n,m;
int a[N],pos[N],al[N],ar[N];
stack<pair<int,int>> d[N];
priority_queue<pair<int,int>> stk; bool solve(int r) {
if(!stk.size()) return 0;
int ql=stk.top().first,qid=stk.top().second;
al[qid]=query(1,1,n,ql,r);
if(!al[qid]) return 0;
ar[qid]=r; stk.pop(); return 1;
} int main() {
scanf("%d",&n);
for(int i=1; i<=n; ++i) {
scanf("%d",&a[i]);
pos[a[i]]=i;
}
scanf("%d",&m);
for(int i=1,x,y; i<=m; ++i) {
scanf("%d%d",&x,&y);
d[y].push(make_pair(x,i));
}
build(1,1,n);
for(int i=1; i<=n; ++i) {
if(a[i]>1&&pos[a[i]-1]<i) modify(1,1,n,1,pos[a[i]-1]);
if(a[i]<n&&pos[a[i]+1]<i) modify(1,1,n,1,pos[a[i]+1]);
while(d[i].size()) stk.push(d[i].top()),d[i].pop();
while(solve(i));
}
for(int i=1; i<=m; ++i) {
printf("%d %d\n",al[i],ar[i]);
}
return 0;
}

[CERC2017] Intrinsic Interval的更多相关文章

  1. [CERC2017]Intrinsic Interval——扫描线+转化思想+线段树

    [CERC2017]Intrinsic Interval https://www.luogu.org/blog/ywycasm/solution-p4747# 这种“好的区间”,见得还是比较多的了. ...

  2. [CERC2017]Intrinsic Interval(神仙+线段树)

    题目大意:给一个1-n的排列,有一堆询问区间,定义一个好的区间为它的值域区间长度等于它的区间长度,求包这个询问区间的最小好的区间. 题解 做法太神了,根本想不到. %%%i207m. 结论:当一个区间 ...

  3. [CERC2017]Intrinsic Interval[scc+线段树优化建图]

    题意 给定一个长度为 \(n\) 的排列,有 \(q\) 次询问,每次询问一个区间 \([l,r]\) ,找到最小的包含 \([l,r]\) 的区间,满足这个区间包含了一段连续的数字. \(n\leq ...

  4. 洛谷 P4747 [CERC2017]Intrinsic Interval 线段树维护连续区间

    题目描述 题目传送门 分析 考虑对于 \([l,r]\),如何求出包住它的长度最短的好区间 做法就是用一个指针从 \(r\) 向右扫,每次查询以当前指针为右端点的最短的能包住 \([l,r]\) 的好 ...

  5. Gym - 101620I Intrinsic Interval

    题面在这里! 首先一个非常重要的性质是,两个好的区间的交依然是好的区间. 有了这个性质,我们只要找到包含某个区间的右端点最小的好区间,然后就是这个区间的答案拉. 至于找右端点最小的好区间就是一个扫描线 ...

  6. [luogu4747]Intrinsic Interval

    有一个结论,答案一定是所有包含其合法区间中$l$最大且$r$最小的 证明比较容易,考虑两个合法区间有交,那么交必然合法,同时交也必然包含该区间,因此这个区间一定是合法的(取$l$最大的和$r$最小的两 ...

  7. 2017-2018 ACM-ICPC, Central Europe Regional Contest (CERC 17)

    A. Assignment Algorithm 按题意模拟即可. #include<stdio.h> #include<iostream> #include<string ...

  8. 2017 CERC

    2017 CERC Problem A:Assignment Algorithm 题目描述:按照规则安排在飞机上的座位. solution 模拟. 时间复杂度:\(O(nm)\) Problem B: ...

  9. 【转】The difference between categorical(Nominal ), ordinal and interval variables

    What is the difference between categorical, ordinal and interval variables? In talking about variabl ...

随机推荐

  1. RabbitMQ 保证消息不丢失

    参考:https://www.imooc.com/article/49814 发送消息的时候,加上messageId字段,数据库记录消息日志表 ,插入的时候为发送中 当收到消息的时候,更改为已发送 , ...

  2. with原理__enter__、__exit__

    Python对with的处理还很聪明.基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法. 紧跟with后面的语句被求值后,返回对象的__enter__( ...

  3. PostGIS导出SHP中文乱码

    设置系统的环境变量 PGCLIENTENCODING=GBK,退出PostgreSQL重新登錄,执行成功!

  4. 三、OpenStack创建域,项目,用户和角色,验证,创建客户端脚本

    一.Identity服务为每个OpenStack服务提供身份验证服务. 身份验证服务使用域,项目,用户和 角色的组合. 1.创建service 项目 # openstack project creat ...

  5. Win Server 2003 10条小技巧

    微软推出Windows Server 2003已经有一段时间了,但是,由于它是一个面向企业用户的服务器操作系统,所以,没有引起更多个人用户的注意.实际上,简单地改变一下系统的设置,您也可以将Windo ...

  6. hdu1201 java

    题意: 求某人从出生到18岁生日所经过的天数.如果这个人没有18岁生日,就输出-1. 思路: 通过毫秒值计算天数. 利用:来自https://www.cnblogs.com/xiohao/p/5294 ...

  7. fidderl 录制导出 jmeter格式文件

    总共需要五步 1.下载扩展脚本 2.将下载后的文件剪切到 fiddler 安装目录下 3.重新启动fillder 4.设置筛选条件 5.录制完成后导出文件 1.下载扩展脚本 首先需要下载支持jmete ...

  8. CF498C. Array and Operations [二分图]

    CF498C. Array and Operations 题意: 给定一个长为 n 的数组,以及 m 对下标 (a, b) 且满足 a + b 为奇数,每次操作可以将同一组的两个数同时除以一个公约数 ...

  9. [POJ1193][NOI1999]内存分配(链表+模拟)

    题意 时 刻 T 内存占用情况 进程事件 0 1 2 3 4 5 6 7 8 9 进程A申请空间(M=3, P=10)<成功> 1 A 2 A B 进程B申请空间(M=4, P=3)< ...

  10. 机器学习——KNN算法(k近邻算法)

    一 KNN算法 1. KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分 ...