• Gym


    题面在这里!

        首先一个非常重要的性质是,两个好的区间的交依然是好的区间。

        有了这个性质,我们只要找到包含某个区间的右端点最小的好区间,然后就是这个区间的答案拉。

        至于找右端点最小的好区间就是一个扫描线问题啦 (和我之前出的那个题有点像,只不过从树上放到了序列上)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=100005;
    #define pb push_back
    #define lc (o<<1)
    #define mid (l+r>>1)
    #define rc ((o<<1)|1)
    
    inline int read(){
    	int x=0; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar());
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    	return x;
    }
    
    void W(int x){ if(x>=10) W(x/10); putchar(x%10+'0');}
    
    struct ask{
        int L,num;
        bool operator <(const ask &u)const{
        	return L<u.L;
    	}
    };
    vector<ask> g[N];
    multiset<ask> s;
    multiset<ask> :: iterator it;
    int n,a[N],p[N],mx[N*4],pos[N*4],Q;
    int le,ri,w,al[N],ar[N],M,P,tag[N*4];
    
    inline void mt(int o){
    	mx[o]=max(mx[lc],mx[rc]);
    	pos[o]=(mx[rc]==mx[o]?pos[rc]:pos[lc]);
    }
    
    inline void work(int o,int der){ tag[o]+=der,mx[o]+=der;}
    
    inline void pd(int o){ if(tag[o]) work(lc,tag[o]),work(rc,tag[o]),tag[o]=0;}
    
    void build(int o,int l,int r){
    	mx[o]=r,pos[o]=r;
    	if(l==r) return;
    	build(lc,l,mid),build(rc,mid+1,r);
    }
    
    void update(int o,int l,int r){
    	if(l>=le&&r<=ri){ work(o,w); return;}
    	pd(o);
    	if(le<=mid) update(lc,l,mid);
    	if(ri>mid) update(rc,mid+1,r);
    	mt(o);
    }
    
    void query(int o,int l,int r){
    	if(l>=le&&r<=ri){ if(mx[o]>M) M=mx[o],P=pos[o]; return;}
    	pd(o);
    	if(ri>mid) query(rc,mid+1,r);
    	if(le<=mid) query(lc,l,mid);
    }
    
    inline bool can(int cc){
    	le=1,ri=it->L,M=P=0;
    	query(1,1,n);
    	if(M==cc){ al[it->num]=P,ar[it->num]=cc; return 1;}
    	return 0;
    }
    
    inline void solve(){
    	build(1,1,n),w=1;
    	ask inf=(ask){233333,0};
    	
    	for(int i=1;i<=n;i++){
    		for(ask x:g[i]) s.insert(x);
    		
    		ri=p[a[i]-1],le=1;
    		if(ri&&ri<i) update(1,1,n);
    		
    		ri=p[a[i]+1],le=1;
    		if(ri&&ri<i) update(1,1,n);
    		
    		for(;s.size();s.erase(it)){
    			it=--s.lower_bound(inf);
    			if(!can(i)) break;
    		}
    	}
    }
    
    int main(){
    //	freopen("data.in","r",stdin);
    //	freopen("data.out","w",stdout);
    	
    	n=read();
    	for(int i=1;i<=n;i++) p[a[i]=read()]=i;
    	Q=read();
    	for(int i=1,l,r;i<=Q;i++){
    		l=read(),r=read();
    		g[r].pb((ask){l,i});
    	}
    	
    	solve();
    	
    	for(int i=1;i<=Q;i++) W(al[i]),putchar(' '),W(ar[i]),puts("");
    	return 0;
    }
    
  • 相关阅读:
    如何将JS中object转换为字符串
    验证码的实现
    JSP中解决session超时跳转到登陆页面并跳出iframe框架或局部区域的方法
    java 后台封装json数据学习总结
    ztree复选框
    左偏树详解
    Docker 入门
    linux 多进程
    派生类构造函数顺序
    20210203 7. 分库分表实战及中间件
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9276617.html
Copyright © 2020-2023  润新知