[luogu4747]Intrinsic Interval
有一个结论,答案一定是所有包含其合法区间中$l$最大且$r$最小的
证明比较容易,考虑两个合法区间有交,那么交必然合法,同时交也必然包含该区间,因此这个区间一定是合法的(取$l$最大的和$r$最小的两个区间求交)且必然最小
将询问离线,类似于[cf997E][https://www.cnblogs.com/PYWBKTDA/p/13912635.html],枚举右端点$r$,维护一棵线段树记录区间$[l,r]$的$(mx-mn)-(r-l)$,相当于判断当前还没有找到最小的$r$的询问中$[1,l]$是否存在
很明显$[1,l]$是否存在与$l$单调,即$l$越大越容易存在,那么维护一个堆,从大到小弹出$l$来判定,时间复杂度即为$o(n\log_{2}n)$(如果存在还要找到最后一次,即维护最后一次出现)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 120005 4 #define pii pair<int,int> 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 priority_queue<pii>q; 9 vector<pii>v[N]; 10 int n,m,x,y,a[N],mn[N],mx[N],f[N<<2],pos[N<<2],tag[N<<2]; 11 pii ans[N]; 12 void upd(int k,int x){ 13 f[k]+=x; 14 tag[k]+=x; 15 } 16 void up(int k){ 17 f[k]=min(f[L],f[R]); 18 if (f[k]==f[R])pos[k]=pos[R]; 19 else pos[k]=pos[L]; 20 } 21 void down(int k){ 22 upd(L,tag[k]); 23 upd(R,tag[k]); 24 tag[k]=0; 25 } 26 void build(int k,int l,int r){ 27 f[k]=1; 28 pos[k]=r; 29 if (l==r)return; 30 build(L,l,mid); 31 build(R,mid+1,r); 32 } 33 void update(int k,int l,int r,int x,int y,int z){ 34 if ((l>y)||(x>r))return; 35 if ((x<=l)&&(r<=y)){ 36 upd(k,z); 37 return; 38 } 39 down(k); 40 update(L,l,mid,x,y,z); 41 update(R,mid+1,r,x,y,z); 42 up(k); 43 } 44 int query(int k,int l,int r,int x,int y){ 45 if ((l>y)||(x>r))return 0x3f3f3f3f; 46 if ((x<=l)&&(r<=y))return f[k]; 47 down(k); 48 return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 49 } 50 int find(int k,int l,int r,int x,int y){ 51 if ((f[k])||(l>y)||(x>r))return 0; 52 if ((x<=l)&&(r<=y))return pos[k]; 53 down(k); 54 return max(find(L,l,mid,x,y),find(R,mid+1,r,x,y)); 55 } 56 int main(){ 57 scanf("%d",&n); 58 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 59 scanf("%d",&m); 60 for(int i=1;i<=m;i++){ 61 scanf("%d%d",&x,&y); 62 v[y].push_back(make_pair(x,i)); 63 } 64 build(1,1,n); 65 for(int i=1;i<=n;i++){ 66 update(1,1,n,1,i,-1); 67 while ((mn[0])&&(a[mn[mn[0]]]>a[i])){ 68 if (mn[0]==1)update(1,1,n,1,mn[mn[0]],a[mn[mn[0]]]-a[i]); 69 else update(1,1,n,mn[mn[0]-1]+1,mn[mn[0]],a[mn[mn[0]]]-a[i]); 70 mn[0]--; 71 } 72 mn[++mn[0]]=i; 73 while ((mx[0])&&(a[mx[mx[0]]]<a[i])){ 74 if (mx[0]==1)update(1,1,n,1,mx[mx[0]],a[i]-a[mx[mx[0]]]); 75 else update(1,1,n,mx[mx[0]-1]+1,mx[mx[0]],a[i]-a[mx[mx[0]]]); 76 mx[0]--; 77 } 78 mx[++mx[0]]=i; 79 for(int j=0;j<v[i].size();j++)q.push(v[i][j]); 80 while (!q.empty()){ 81 pii o=q.top(); 82 if (query(1,1,n,1,o.first))break; 83 q.pop(); 84 ans[o.second]=make_pair(find(1,1,n,1,o.first),i); 85 } 86 } 87 for(int i=1;i<=m;i++)printf("%d %d\n",ans[i].first,ans[i].second); 88 }