• [cf997E]Good Subsegments


    一个区间为好区间当且仅当$max_{lle ile r}a_{i}-min_{lle ile r}a_{i}=r-l$,考虑固定右端点$r$,维护所有左端点$l$的上述式子左-右的值,那么答案即求0的个数,也就是最小值的个数(该值必然非负且$l=r$时必然为0)

    如何维护右端点移动:先将所有位置减1,再用单调栈找到之前第一个小于和大于其的位置,然后由于这两个位置中必然有一个为$r-1$,不需要考虑,记剩下的位置为$x$,不妨假设$a_{x}>a_{r}$

    那么也就是考虑以$a[1..r]$这个前缀的后缀最大值,也即单调栈中被$r$弹出的元素,因此对于被弹出的两个元素中间,加上$a_{r}-先弹出的元素$即可($a_{x}<a_{r}$类似)

    对于多组询问,将询问离线并记录在对应位置上,即查询区间$[l,r]$最小值次数(令未修改的位置为1)

    维护一个时间标记,表示当前的sum已经统计到该时间,再下传修改同时也要下传时间标记,因此在上一个时间标记到现在其最小值次数不变,即可维护

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 120005
     4 #define ll long long
     5 #define L (k<<1)
     6 #define R (L+1)
     7 #define mid (l+r>>1)
     8 vector<pair<int,int> >v[N];
     9 int n,m,x,y,a[N],mn[N],mx[N],f[N<<2],tag[N<<2],tim[N<<2],tot[N<<2];
    10 ll ans[N],sum[N<<2];
    11 void upd(int k,int x){
    12     f[k]+=x;
    13     tag[k]+=x;
    14 }
    15 void upd_time(int k,int x){
    16     sum[k]+=1LL*x*tot[k];
    17     tim[k]+=x;
    18 }
    19 void up(int k){
    20     f[k]=min(f[L],f[R]);
    21     tot[k]=0;
    22     if (f[k]==f[L])tot[k]+=tot[L];
    23     if (f[k]==f[R])tot[k]+=tot[R];
    24     sum[k]=sum[L]+sum[R];
    25 }
    26 void down(int k){
    27     upd(L,tag[k]);
    28     upd(R,tag[k]);
    29     tag[k]=0;
    30     if (f[L]==f[k])upd_time(L,tim[k]);
    31     if (f[R]==f[k])upd_time(R,tim[k]);
    32     tim[k]=0;
    33 }
    34 void build(int k,int l,int r){
    35     f[k]=1;
    36     tot[k]=r-l+1;
    37     if (l==r)return;
    38     build(L,l,mid);
    39     build(R,mid+1,r);
    40 }
    41 void update(int k,int l,int r,int x,int y,int z){
    42     if ((l>y)||(x>r))return;
    43     if ((x<=l)&&(r<=y)){
    44         upd(k,z);
    45         return;
    46     }
    47     down(k);
    48     update(L,l,mid,x,y,z);
    49     update(R,mid+1,r,x,y,z);
    50     up(k);
    51 }
    52 ll query(int k,int l,int r,int x,int y){
    53     if ((l>y)||(x>r))return 0;
    54     if ((x<=l)&&(r<=y))return sum[k];
    55     down(k);
    56     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
    57 }
    58 int main(){
    59     scanf("%d",&n);
    60     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    61     scanf("%d",&m);
    62     for(int i=1;i<=m;i++){
    63         scanf("%d%d",&x,&y);
    64         v[y].push_back(make_pair(x,i));
    65     }
    66     build(1,1,n);
    67     for(int i=1;i<=n;i++){
    68         update(1,1,n,1,i,-1);
    69         while ((mn[0])&&(a[mn[mn[0]]]>a[i])){
    70             if (mn[0]==1)update(1,1,n,1,mn[mn[0]],a[mn[mn[0]]]-a[i]);
    71             else update(1,1,n,mn[mn[0]-1]+1,mn[mn[0]],a[mn[mn[0]]]-a[i]);
    72             mn[0]--;
    73         }
    74         mn[++mn[0]]=i; 
    75         while ((mx[0])&&(a[mx[mx[0]]]<a[i])){
    76             if (mx[0]==1)update(1,1,n,1,mx[mx[0]],a[i]-a[mx[mx[0]]]);
    77             else update(1,1,n,mx[mx[0]-1]+1,mx[mx[0]],a[i]-a[mx[mx[0]]]);
    78             mx[0]--;
    79         }
    80         mx[++mx[0]]=i;
    81         upd_time(1,1);
    82         for(int j=0;j<v[i].size();j++)ans[v[i][j].second]=query(1,1,n,v[i][j].first,i);
    83     }
    84     for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
    85 } 
    View Code
  • 相关阅读:
    javaee 第六周作业
    javaee 第五周作业
    javaee 第四周作业
    第三周作业
    第二周作业xml学习情况
    javaWeb 中http请求 get 与 post的区别
    第八周
    第七周
    第六周
    第五周
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13912635.html
Copyright © 2020-2023  润新知