• [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(nlog_{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
    ",ans[i].first,ans[i].second);
    88 }
    View Code
  • 相关阅读:
    在centos上搭建Git服务器
    glog日志库移植Android平台
    水葱
    路易斯安娜鸢尾
    再力花
    矮生百慕大
    洒金珊瑚
    八角金盘
    锦绣杜鹃
    茶梅球
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13964441.html
Copyright © 2020-2023  润新知