和Leo一起做爱线段树的好孩子【九校2D1T3】优美序列

Lxy养了N头奶牛,他把N头奶牛用1..N编号,第i头奶牛编号为i。为了让奶牛多产奶,每天早上他都会让奶牛们排成一排做早操。奶牛们是随机排列的。在奶牛排列中,如果一段区间[L,R]中的数从小到大排列后是连续的,他认为这段区间是优美的。比如奶牛排列为:(3, 1, 7, 5, 6, 4, 2),区间[3,6]是优美的,它包含4,5,6,7连续的四个数,而区间[1,3] 是不优美的。Lxy的问题是:对于给定的一个区间[L,R](1<=L<=R<=N), 他想知道,包含区间[L,R]的最短优美区间,比如区间[1,3]的最短优美区间是[1,7]。 

数据随机说明优美区间并不多

预处理出来

然后离线操作

线段树维护到当前点最短的符合条件的区间

#include
#include
#include
#include
#include
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
inline void read(int &x){
	x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
const int N=1e5+100;
const int INF=1e9+7;
struct Segment_Tree{
	int val[N];
	struct Node{
		int lson,rson,Mx,Mn;
	}T[N<<2];
	inline void PushUp(int p){
//		T[p].Mx=max(T[lc].Mx,T[rc].Mx);
		T[p].Mn=min(T[lc].Mn,T[rc].Mn);
	}
	inline void Build(int p,int l,int r){
		T[p].lson=l;
		T[p].rson=r;
		if(l==r){
			T[p].Mn=T[p].Mx=val[l];
			return;
		}
		int mid=(l+r)>>1;
		Build(lc,l,mid);
		Build(rc,mid+1,r);
		PushUp(p);
	}
	inline void Update(int p,int pos,int val){
		if(T[p].lson==T[p].rson){
			T[p].Mn=min(T[p].Mn,val);
//			T[p].Mx=max(T[p].Mx,val);
			return;
		}
		int mid=(T[p].lson+T[p].rson)>>1;
		if(pos<=mid)Update(lc,pos,val);
		else Update(rc,pos,val);
		PushUp(p);
	}
	inline int QueryMn(int p,int l,int r){
		if(l<=T[p].lson&&T[p].rson<=r){
			return T[p].Mn;
		}
		int mid=(T[p].lson+T[p].rson)>>1;
		int ret=INF;
		if(l<=mid)ret=min(ret,QueryMn(lc,l,r));
		if(mid< r)ret=min(ret,QueryMn(rc,l,r));
		return ret;
	}
	inline int QueryMx(int p,int l,int r){
		if(l<=T[p].lson&&T[p].rson<=r){
			return T[p].Mx;
		}
		int mid=(T[p].lson+T[p].rson)>>1;
		int ret=-INF;
		if(l<=mid)ret=max(ret,QueryMx(lc,l,r));
		if(mid< r)ret=max(ret,QueryMx(rc,l,r));
		return ret;
	} 
}Tree;
int n,m;
struct ST_map{
	int val[N];
	int Mx[21][N];
	int Mn[21][N];
	void Build(){
		for(int i=1;i<=n;++i){
			Mx[0][i]=Mn[0][i]=val[i];
		}
		for(int i=1;i<=20;++i){
			for(int j=1;j<=n;++j){
				if(j+(1<<(i-1))>n)continue;
				Mx[i][j]=max(Mx[i-1][j],Mx[i-1][j+(1<<(i-1))]);
				Mn[i][j]=min(Mn[i-1][j],Mn[i-1][j+(1<<(i-1))]);
			}
		}
	}
	int QueryMx(int l,int r){
		int k=log2((double)(r-l+1));
		return max(Mx[k][l],Mx[k][r-(1<

 

你可能感兴趣的:(线段树)