zoukankan      html  css  js  c++  java
  • [hdu7062]A Simple Problem

    称序列${a_{1},a_{2},...,a_{n}}$​的答案为$min_{0le ile n-k}(max_{i<jle i+k}a_{j})$​​(特别的,若$n<k$​则为$infty$​)​​

    将序列按$k$分段,每一段长度为$k$(最后一段长度可以小于$k$),那么恰有$lceilfrac{n}{k} ceil$​​​​​​​​​段

    考虑维护第$i$段和第$i+1$​​​​段拼接成的序列的答案,那么如果相邻两段都全在修改或查询区间内,直接再维护一棵线段树即可(支持区间加和区间取$min$),并对剩下$o(1)$个暴力计算即可(单点修改)

    关于如何"暴力计算",做法如下:

    问题即选择第$i$段的一个后缀和第$i+1$段的一个前缀(都可以为空),长度和为$k$并最小化两者的最大值

    (另外,如果是查询,还会对其长度有一定限制,但并不影响下面的做法)

    显然两者随长度的增长单调不下降,因此即需要找到最短的后缀使得其对应的前缀(长度和为$k$​)最大值小于后缀最大值(类似地找到最短的后缀),那么答案即这两个位置

    简单的做法即二分+线段树做到$o(log^{2}n)$,但注意到可以对每一段都建一棵线段树,且让两者形态相同(将最后一段长度补至$k$),那么就可以在两棵线段树上一起二分,时间复杂度降为$o(log n)$

    最终,总复杂度为$o(qlog n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 3000005
      4 #define oo 0x3f3f3f3f
      5 #define mid (l+r>>1)
      6 int t,n,m,q,p,l,r,x;
      7 namespace VAL{
      8     int V,Rt,ls[N],rs[N],tag[N],f[N];
      9     unordered_map<int,int>rt;
     10     void init(){
     11         V=Rt=0;
     12         rt.clear();
     13     }
     14     int New(){
     15         int k=++V;
     16         ls[k]=rs[k]=tag[k]=f[k]=0;
     17         return k;
     18     }
     19     void upd(int &k,int x){
     20         if (!k)k=New();
     21         tag[k]+=x,f[k]+=x;
     22     }
     23     void up(int k){
     24         f[k]=max(f[ls[k]],f[rs[k]])+tag[k];
     25     }
     26     void down(int k){
     27         if (!tag[k])return;
     28         upd(ls[k],tag[k]);
     29         upd(rs[k],tag[k]);
     30         tag[k]=0;
     31     }
     32     void update(int &k,int l,int r,int x,int y,int z){
     33         if ((l>y)||(x>r))return;
     34         if (!k)k=New();
     35         if ((x<=l)&&(r<=y)){
     36             upd(k,z);
     37             return;
     38         }
     39         update(ls[k],l,mid,x,y,z);
     40         update(rs[k],mid+1,r,x,y,z);
     41         up(k);
     42     }
     43     void get_tag(int k,int l,int r,int x){
     44         if (!k)return;
     45         if (l==r){
     46             upd(rt[x],tag[k]),tag[k]=0;
     47             return;
     48         }
     49         down(k);
     50         if (x<=mid)get_tag(ls[k],l,mid,x);
     51         else get_tag(rs[k],mid+1,r,x);
     52         up(k);
     53     }
     54     int query(int k,int l,int r,int x,int y){
     55         if ((l>y)||(x>r))return -oo;
     56         if ((!k)||(x<=l)&&(r<=y))return f[k];
     57         return max(query(ls[k],l,mid,x,y),query(rs[k],mid+1,r,x,y))+tag[k];
     58     }
     59     int find(int k1,int k2,int l,int r,int x,int y){
     60         if (l==r)return l;
     61         down(k1),down(k2);
     62         int xx=max(x,f[rs[k1]]),yy=max(y,f[ls[k2]]);
     63         if (xx>=yy)return find(rs[k1],rs[k2],mid+1,r,x,yy);
     64         return find(ls[k1],ls[k2],l,mid,xx,y);
     65     }
     66     void update(int pos,int l,int r,int x){
     67         if (l<=r){
     68             if (!pos)update(Rt,1,n/m,l,r,x);
     69             else update(rt[pos],1,m,l,r,x);
     70         }
     71     }
     72     int query(int pos,int l,int r){
     73         if (l>r)return oo;
     74         get_tag(Rt,1,n/m,pos),get_tag(Rt,1,n/m,pos+1);
     75         l=min(max(find(rt[pos],rt[pos+1],1,m,-oo,-oo),l),r);
     76         int ans=max(query(rt[pos],1,m,l,m),query(rt[pos+1],1,m,1,l-1));
     77         if (l<r)ans=min(ans,max(query(rt[pos],1,m,l+1,m),query(rt[pos+1],1,m,1,l)));
     78         return ans;
     79     }
     80 };
     81 namespace ANS{
     82     int V,rt,ls[N],rs[N],tag[N],f[N];
     83     void init(){
     84         V=rt=0;
     85     }
     86     int New(){
     87         int k=++V;
     88         ls[k]=rs[k]=tag[k]=f[k]=0;
     89         return k;
     90     }
     91     void upd(int &k,int x){
     92         if (!k)k=New();
     93         tag[k]+=x,f[k]+=x;
     94     }
     95     void up(int k){
     96         f[k]=min(f[ls[k]],f[rs[k]])+tag[k];
     97     }
     98     void down(int k){
     99         if (!tag[k])return;
    100         upd(ls[k],tag[k]);
    101         upd(rs[k],tag[k]);
    102         tag[k]=0;
    103     }
    104     void update(int &k,int l,int r,int x,int y){
    105         if (!k)k=New();
    106         if (l==r){
    107             tag[k]=0,f[k]=y;
    108             return;
    109         }
    110         down(k);
    111         if (x<=mid)update(ls[k],l,mid,x,y);
    112         else update(rs[k],mid+1,r,x,y);
    113         up(k);
    114     }
    115     void update(int &k,int l,int r,int x,int y,int z){
    116         if ((l>y)||(x>r))return;
    117         if (!k)k=New();
    118         if ((x<=l)&&(r<=y)){
    119             upd(k,z);
    120             return;
    121         }
    122         update(ls[k],l,mid,x,y,z);
    123         update(rs[k],mid+1,r,x,y,z);
    124         up(k);
    125     }
    126     int query(int k,int l,int r,int x,int y){
    127         if ((l>y)||(x>r))return oo;
    128         if ((!k)||(x<=l)&&(r<=y))return f[k];
    129         return min(query(ls[k],l,mid,x,y),query(rs[k],mid+1,r,x,y))+tag[k];
    130     }
    131     void update(int pos,int x){
    132         update(rt,1,n/m,pos,x);
    133     }
    134     void update(int l,int r,int x){
    135         if (l<=r)update(rt,1,n/m,l,r,x);
    136     }
    137     int query(int l,int r){
    138         if (l>r)return oo;
    139         return query(rt,1,n/m,l,r);
    140     }
    141 };
    142 int bl(int k){
    143     return (k+m-1)/m;
    144 }
    145 int st(int k){
    146     return (k-1)*m+1;
    147 }
    148 int ed(int k){
    149     return k*m;
    150 }
    151 void update(int l,int r,int x){
    152     int ll=bl(l),rr=bl(r);
    153     if (ll==rr)VAL::update(ll,l-st(ll)+1,r-st(ll)+1,x);
    154     else{
    155         VAL::update(0,ll+1,rr-1,x);
    156         VAL::update(ll,l-st(ll)+1,m,x);
    157         VAL::update(rr,1,r-st(rr)+1,x);
    158         ANS::update(ll+1,rr-2,x);
    159     }
    160     if (ll>1)ANS::update(ll-1,VAL::query(ll-1,1,m));
    161     if (ll<n/m)ANS::update(ll,VAL::query(ll,1,m));
    162     if (ll<rr-1)ANS::update(rr-1,VAL::query(rr-1,1,m));
    163     if ((ll<rr)&&(rr<n/m))ANS::update(rr,VAL::query(rr,1,m));
    164 }
    165 int query(int l,int r){
    166     int ll=bl(l),rr=bl(r+1),ans=ANS::query(ll+1,rr-2);
    167     if (ll+1==rr)return min(ans,VAL::query(ll,l-st(ll)+1,r-st(rr)+2));
    168     return min(ans,min(VAL::query(ll,l-st(ll)+1,m),VAL::query(rr-1,1,r-st(rr)+2)));
    169 }
    170 int main(){
    171     scanf("%d",&t);
    172     while (t--){
    173         scanf("%d%d%d",&n,&m,&q);
    174         n=(n+m-1)/m*m;
    175         VAL::init(),ANS::init();
    176         for(int i=1;i<=q;i++){
    177             scanf("%d%d%d",&p,&l,&r);
    178             if (p==1){
    179                 scanf("%d",&x);
    180                 update(l,r,x);
    181             }
    182             if (p==2)printf("%d
    ",query(l,r));
    183         }
    184     }
    185     return 0;
    186 }
    View Code
  • 相关阅读:
    详解Webpack-dev-server的proxy用法
    .sync修饰符
    [Vue]createElement参数
    ElementUi学习笔记
    A5000项目阅读笔记
    webpack学习-10天搞定webpack4
    bhuilder 采坑日记-大小写问题
    angularjs:$$animateJs is not a function 错误
    webpack4 Cannot find module '@babel/core'
    算法-图论-最短路径-Dijsktra算法
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15148498.html
Copyright © 2011-2022 走看看