码迷,mamicode.com
首页 > 其他好文 > 详细

P4747 [CERC2017]Intrinsic Interval

时间:2019-09-06 20:11:51      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:lse   就是   hup   oid   lcs   com   排序   using   pop   

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,'\n');
    return 0;
}

P4747 [CERC2017]Intrinsic Interval

标签:lse   就是   hup   oid   lcs   com   排序   using   pop   

原文地址:https://www.cnblogs.com/LLCSBlog/p/11477908.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!