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

Gym - 101620I Intrinsic Interval

时间:2018-07-07 11:23:33      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:main   long   最小   push   read   和我   puts   个性   int   

题面在这里!

 

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

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

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

 

#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;
}

 

Gym - 101620I Intrinsic Interval

标签:main   long   最小   push   read   和我   puts   个性   int   

原文地址:https://www.cnblogs.com/JYYHH/p/9276617.html

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