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]。c++
第一行为一个整数N,表示奶牛的个数。
第二行为1到N的一个排列,表示奶牛的队伍。
第三行为一个整数M,表示有M个询问。
后面有M行,每行有两个整数L,R表示询问区间。数组
输出为M行,每行两个整数,表示包含询问区间的最短优美区间。ui
input
7
3 1 7 5 6 4 2
3
3 6
7 7
1 3
output
3 6
7 7
1 7spa
input
10
2 1 4 3 5 6 7 10 8 9
5
2 3
3 7
4 7
4 8
7 8
output
1 4
3 7
3 7
3 10
7 10code
15%的数据知足: 1 <=N,M <= 15;
50%的数据知足:1 <=N,M <= 1000。
100%的数据知足:1 <=N,M <= 100000。排序
为了给出题人留面子,不让他被骂出个题只有一种解法并且只有满分解法,我先给个80分作法。
预处理一个数组pos[i],表示数i在原数组的位置(第几个数)。
在询问区间内找一个最小值和最大值,做为新的l和r,新的l和r做为一个询问区间,在pos数组里找一个最小值和最大值,他们再做为新的l和r,造成询问区间,在原数组寻找最小值和最大值,并再次重复刚才的操做……
上述过程可能很无脑很中二,然而这就是模拟题意找出答案的过程。
最大值最小值用st表预处理,一共四个st表,比线段树好写……
那么……
正解是分治,像归并排序那样。
不断求[l,mid] [mid+1,r]的优美序列,直到分红[mid,mid+1]
能够证实是正确的。
事实上分治作的熟练的人可能一眼秒这道题。get
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; template<class T> void read(T &res) { res = 0; T f = 1; char cc = getchar(); while(cc < '0' || cc > '9') { if(cc == '-') f = -1; cc = getchar(); } while(cc >= '0' && cc <= '9') { res = res * 10 + cc - '0'; cc = getchar(); } res *= f; } const int maxn = 1e5 + 5; int n,m; int seqmin[maxn][50]; int posmin[maxn][50]; int seqmax[maxn][50]; int posmax[maxn][50]; int ansl,ansr; void init() { for(int j=1;(1<<j) <= n;j++) { for(int i=0;i+(1<<j)-1 <= n;i++) { seqmax[i][j] = max(seqmax[i][j-1],seqmax[i+(1<<(j-1))][j-1]); // 1 seqmin[i][j] = min(seqmin[i][j-1],seqmin[i+(1<<(j-1))][j-1]); // 2 posmax[i][j] = max(posmax[i][j-1],posmax[i+(1<<(j-1))][j-1]); // 3 posmin[i][j] = min(posmin[i][j-1],posmin[i+(1<<(j-1))][j-1]); // 4 } } } int query(int l,int r,int ju) { int t = int(log((double)(r - l + 1)) / log(2.0)); if(ju == 1) return max(seqmax[l][t],seqmax[r-(1<<t)+1][t]); if(ju == 2) return min(seqmin[l][t],seqmin[r-(1<<t)+1][t]); if(ju == 3) return max(posmax[l][t],posmax[r-(1<<t)+1][t]); if(ju == 4) return min(posmin[l][t],posmin[r-(1<<t)+1][t]); } void change(int inl,int inr) { int templ,tempr,endl,endr; templ = query(inl,inr,2); tempr = query(inl,inr,1); endl = query(templ,tempr,4); endr = query(templ,tempr,3); if(endl == inl && endr == inr) { ansl = endl; ansr = endr; return; } else change(endl,endr); } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); read(n); for(int i=1;i<=n;i++) read(seqmin[i][0]),seqmax[i][0] = seqmin[i][0]; for(int i=1;i<=n;i++) posmax[seqmin[i][0]][0] = i,posmin[seqmin[i][0]][0] = i; init(); read(m); while(m--) { int l,r; read(l);read(r); change(l,r); printf("%d %d\n",ansl,ansr); } return 0; }
#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) 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("sequence.in","r",stdin); freopen("sequence.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); p[a[i]]=i; }; scanf("%d",&Q); for(int i=1,l,r;i<=Q;i++){ scanf("%d %d",&l,&r); g[r].pb((ask){l,i}); } solve(); for(int i=1;i<=Q;i++) printf("%d %d\n",al[i],ar[i]); return 0; }