zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Redis 学习(二十)服务器
    Redis 学习(十八)连接
    Redis学习(十七) 脚本
    Redis学习(十六)事务
    Redis学习(十四) 发布订阅
    python中如何使用requests模块下载文件并获取进度提示?
    Python实例获取mp3文件的tag信息
    python 视频处理,提取视频相关帧,读取Excel
    爬虫数据采集技术趋势-智能化解析
    Python中文转拼音代码(支持全拼和首字母缩写)
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11477908.html
Copyright © 2011-2022 走看看