Description
![](https://i-blog.csdnimg.cn/blog_migrate/ea35d8943e33d03bdeb67688dca819fe.png)
Input
![](https://i-blog.csdnimg.cn/blog_migrate/a615b3fcac2799c229842b74e73c448e.png)
Output
![](https://i-blog.csdnimg.cn/blog_migrate/387ffdf4149ec0ab9ea8d807b6361fe6.png)
Sample Input
Sample Input17
3 1 7 5 6 4 2
3
3 6
7 7
1 3 Sample Input2102 1 4 3 5 6 7 10 8 9 52 3 3 7 4 7 4 8 7 8
Sample Output
Sample Output13 67 7 1 7
Sample Output21 43 7 3 7 3 10 7 10
Data Constraint
![](https://i-blog.csdnimg.cn/blog_migrate/246a55222e39ceb3d4c489054eae77a9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f8bd3a60dc1d411a7443e98f34573e9e.png)
题解
- 倍增维护区间最大最小值,维护坐标做小最大值
- 然后就可以在倍增上查询包含该区间的完美序列的坐标的做大做小值
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 const int N=1e5+10,M=30; 7 int n,m,mi[M],mx[N][M],mn[N][M],Mx[N][M],Mn[N][M],p[N],a[N]; 8 int querymx(int x,int y) { int k=p[y-x+1]; return max(mx[x][k],mx[y-mi[k]+1][k]); } 9 int querymn(int x,int y) { int k=p[y-x+1]; return min(mn[x][k],mn[y-mi[k]+1][k]); } 10 int queryMx(int x,int y) { int k=p[y-x+1]; return max(Mx[x][k],Mx[y-mi[k]+1][k]); } 11 int queryMn(int x,int y) { int k=p[y-x+1]; return min(Mn[x][k],Mn[y-mi[k]+1][k]); } 12 int main() 13 { 14 freopen("sequence.in","r",stdin),freopen("sequence.out","w",stdout); 15 scanf("%d",&n); for (int i=0;i<=20;i++) mi[i]=1<<i; 16 for (int i=1;i<=n;i++) scanf("%d",&a[i]),mx[i][0]=mn[i][0]=a[i],Mx[a[i]][0]=Mn[a[i]][0]=i,p[i]=(int)log2(i); 17 for (int i=n-1;i>=1;i--) for (int j=1;i+mi[j]-1<=n;j++) 18 mx[i][j]=max(mx[i][j-1],mx[i+mi[j-1]][j-1]),Mx[i][j]=max(Mx[i][j-1],Mx[i+mi[j-1]][j-1]),mn[i][j]=min(mn[i][j-1],mn[i+mi[j-1]][j-1]),Mn[i][j]=min(Mn[i][j-1],Mn[i+mi[j-1]][j-1]); 19 scanf("%d",&m); 20 for (int l,r,L,R,flag,boo,num,Max,Min;m;m--) 21 { 22 scanf("%d%d",&l,&r),L=R=flag=boo=num=0; 23 while (l!=L||r!=R) 24 { 25 num++; 26 if (num>70) { flag=1; break; } 27 if (boo) l=L,r=R; 28 Max=querymx(l,r),Min=querymn(l,r),L=queryMn(Min,Max),R=queryMx(Min,Max); 29 if (!boo) boo=1; 30 } 31 if (flag==1) 32 { 33 int i; 34 for (i=min(5,l);i>=1;i--) { Max=querymx(i,n),Min=querymn(i,n); if (Max-Min==n-i) break; } 35 printf("%d %d\n",i,n); 36 }else printf("%d %d\n",l,r); 37 } 38 }