P4747 [CERC2017]Intrinsic Interval

P4747 [CERC2017]Intrinsic Interval

前言

这道题有高大上的析合树做法

不过我不会,可能退役后会考虑学学吧。

这题还有线段树优化建边缩点的好办法。

我还是不会,可能以后会学学吧。

题目大意

(ProblemLink)

其实题目里面讲的很清楚了。

简单的说就是给你一个(1) ~(n)的排列

定义如果一个区间([l,r])是好区间,仅当(l)(r)的序列中的数排序后是连续的。

其实就是有(r-l)个相邻的数。

对于每个询问([L,R])让你找出最小的包含([L,R])的好区间。

思想分析

我们发现好区间显然是可以合并的。

如果([l_1,r_1]),([l_2,r_2](l_1<l_2<r_1<r_2))都是好区间,那么区间([l_1,r_2])肯定是好区间。

于是我们离线询问后使用扫描线

当我们扫描到(r)时,我们就可以处理右端点为(r)的所有询问。

也就是说我们要维护最大的左端点(l)

考虑利用好区间的性质,一个区间([l,r])是好区间仅当区间中有(r-l)个相邻的数

不难想到令线段树的(val[i]=i),设(sa[i])为值(a[i])出现的位置

我们扫描到一个数(a[i])时将区间([1,sa[a[i]-1]],[1,sa[a[i]+1]])都区间加上(1)

那么如果有(val[l]=r)([l,r])一定是好区间。

那么我们对于一个节点维护一个最大(r)值,与(r)出现的位置就可以了。

如果对于一个询问(ql),如果线段树中查询(ql)的最大(r)值等于(qr),我们就成功的回答了这个询问。

代码实现

/*
@Date    : 2019-09-02 20:24:12
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
IL int getint()
{
	RG int xi=0;
	RG char ch=gc;
	bool f=0;
	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
	return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
	if(k<0)k=-k,putchar('-');
	if(k>=10)pi(k/10,0);
	putchar(k%10+'0');
	if(ch)putchar(ch);
}
const int N=1e5+7;
int a[N],b[N];
int mx[N*4],pos[N*4],lz[N*4];
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
int M,P;
IL void pushup(int rt){
	if(mx[ls]>mx[rs])mx[rt]=mx[ls],pos[rt]=pos[ls];
	else mx[rt]=mx[rs],pos[rt]=pos[rs];
}
IL void pusht(int rt,int val){mx[rt]+=val,lz[rt]+=val;}
IL void pushdown(int rt){if(lz[rt])pusht(ls,lz[rt]),pusht(rs,lz[rt]),lz[rt]=0;}
IL void build(int rt,int l,int r){
	mx[rt]=pos[rt]=r;
	if(l==r)return;
	build(ls,l,mid),build(rs,mid+1,r);
}
IL void modify(int rt,int l,int r,int L,int R,int val){
	if(L<=l&&r<=R){pusht(rt,val);return;}
	pushdown(rt);
	if(L<=mid)modify(ls,l,mid,L,R,val);
	if(R>mid)modify(rs,mid+1,r,L,R,val);
	pushup(rt);
}
IL void query(int rt,int l,int r,int L,int R)
{
	if(L<=l&&r<=R){if(mx[rt]>M)M=mx[rt],P=pos[rt];return;}
	pushdown(rt);
	if(R>mid)query(rs,mid+1,r,L,R);
	if(L<=mid)query(ls,l,mid,L,R);
}
int n;
typedef pair<int,int> pii;
#define fi first
#define se second
vector<pii> G[N];
priority_queue<pii> s;
pii ans[N];
bool judge(pii x,int r){
	M=P=0;
	query(1,1,n,1,x.fi);
	if(M==r){ans[x.se]=make_pair(P,M);return 1;}
	return 0;
}
int main(void)
{
	n=gi;
	for(int i=1;i<=n;++i)a[i]=gi,b[a[i]]=i;
	int m=gi;
	for(int i=1;i<=m;++i){int l=gi,r=gi;G[r].push_back(make_pair(l,i));}
	build(1,1,n);
	for(int i=1;i<=n;++i)
	{
		if(a[i]>1&&b[a[i]-1]<=i)modify(1,1,n,1,b[a[i]-1],1);
		if(a[i]<n&&b[a[i]+1]<=i)modify(1,1,n,1,b[a[i]+1],1);
		for(int j=0;j<G[i].size();++j)s.push(G[i][j]);
		while(!s.empty()){
			if(judge(s.top(),i))s.pop();
			else break;
		}
	}
	for(int i=1;i<=m;++i)pi(ans[i].fi,' '),pi(ans[i].se,'
');
	return 0;
}
原文地址:https://www.cnblogs.com/LLCSBlog/p/11477908.html