• 维护直线的线段树:Bzoj1568,Bzoj3938(Uoj88)


    有这样一类线段树,可以维护一些直线方程并对每个点求出最大值。

    首先先看BZOJ1568,输入给你条直线的方程,你需要对于指定的位置求出最大的函数值。

    看到数据范围nlog^2n可做,考虑用线段树去维护。对于每个区间,怎么维护这个区间最高的直线呢?

    显然,对于这个区间而言,最高的直线在各个位置都可能是不同的,看起来不是很可做。但是,我们能对于每个长度为1的区间维护最高的直线。

    然而这样需要把修改push到底,时间复杂度为线性,所以应该怎么办呢?

    考虑标记永久化,对于每个区间,维护其中点最高的直线。然后查询时对于跨越的多个区间的答案取max,这样可以完成查询。

    怎么修改呢?考虑在某个区间上有两条直线(一条原来的,一条新加的),如果一条在整个区间都在另一条之上,那么可以把下面的那条线扔掉,直接返回。否则把中点较高的那一条留在这个区间,另外一条向(这条线)比留下的更高的一个子区间下放。

    考虑这样为什么是对的,因为如果一条线在中点比另一条高,那么在某一边区间这条线一定完全“碾压”另一条线,另外一条是没有用的。所以只把另外一条在另一个子区间下放即可(自己画图或脑补一下就明白了)。

    这个东西的复杂度是log^2n,因为最多修改logn个区间,对于每个区间最多下放logn层。

    然后问题就解决了。

    上代码:

     BZOJ1568:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define debug cout
     6 using namespace std;
     7 const int maxn=5e4+1e2;
     8 
     9 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3];
    10 int mid[maxn<<3];
    11 double k[maxn<<3],b[maxn<<3];
    12 int n,m,cnt;
    13 
    14 inline double f(const double &k,const double &b,const int &x) {
    15     return k * ( x - 1 ) + b;
    16 }
    17 inline void build(int pos,int ll,int rr) {
    18     l[pos] = ll , r[pos] = rr;
    19     if( ll == rr )
    20         return;
    21     mid[pos] = ( ll + rr ) >> 1;
    22     build(lson[pos]=++cnt,ll,mid[pos]);
    23     build(rson[pos]=++cnt,mid[pos]+1,rr);
    24 }
    25 inline void update(int pos,double kk,double bb) {
    26     if( f(kk,bb,l[pos]) <= f(k[pos],b[pos],l[pos]) && f(kk,bb,r[pos]) <= f(k[pos],b[pos],r[pos]) )
    27         return;
    28     if( l[pos] == r[pos] ) {
    29         k[pos] = kk , b[pos] = bb;
    30         return;
    31     }
    32     if( kk > k[pos] ) {
    33         if( f(kk,bb,mid[pos]) > f(k[pos],b[pos],mid[pos]) ) {
    34             update(lson[pos],k[pos],b[pos]);
    35             k[pos] = kk , b[pos] = bb;
    36         }
    37         else
    38             update(rson[pos],kk,bb);
    39     }
    40     else {
    41         if( f(kk,bb,mid[pos]) > f(k[pos],b[pos],mid[pos]) ) {
    42             update(rson[pos],k[pos],b[pos]);
    43             k[pos] = kk , b[pos] = bb;
    44         }
    45         else
    46             update(lson[pos],kk,bb);
    47     }
    48 }
    49 inline double query(int pos,int tar) {
    50     if( l[pos] == r[pos] )
    51         return f(k[pos],b[pos],tar);
    52     if( tar <= mid[pos] )
    53         return max( f(k[pos],b[pos],tar) , query(lson[pos],tar) );
    54     else if( tar > mid[pos] )
    55         return max( f(k[pos],b[pos],tar) , query(rson[pos],tar) );
    56 }
    57 
    58 int main() {
    59     static char com[20];
    60     static double qq,kk,bb;
    61     scanf("%d",&m) , n = 5e4;
    62     build(cnt=1,1,n);
    63     for(int i=1,p;i<=m;i++) {
    64         scanf("%s",com);
    65         if( *com == 'Q' ) {
    66             scanf("%d",&p);
    67             qq = query(1,p);
    68             printf("%d
    ",((int)qq)/100);
    69         }
    70         else {
    71             scanf("%lf%lf",&bb,&kk);
    72             update(1,kk,bb);
    73         }
    74     }
    75     return 0;
    76 }
    View Code

    UOJ88:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cctype>
      6 #define lli long long int
      7 #define debug cout
      8 using namespace std;
      9 const int maxn=1e5+1e2,maxq=6e5+1e2;
     10  
     11 lli srt[maxq];
     12  
     13 inline lli f(const lli &k,const lli &b,const int &x) {
     14     return k * srt[x] + b;
     15 }
     16 
     17 int lson[maxq<<3],rson[maxq<<3];
     18 struct SegmentTree {
     19     int cnt;
     20     lli k[maxq<<3],b[maxq<<3];
     21      
     22     inline void build(int pos,int ll,int rr) {
     23         if( ll == rr )
     24             return;
     25         const int mid = ( ll + rr ) >> 1;
     26         build(lson[pos]=++cnt,ll,mid);
     27         build(rson[pos]=++cnt,mid+1,rr);
     28     }
     29     inline void update(int pos,int l,int r,int ll,int rr,lli kk,lli bb) {
     30         if( rr < l || r < ll )
     31             return;
     32         const int mid = ( l + r ) >> 1;
     33         if( ll <= l && r <= rr ) {
     34             if( f(kk,bb,l) <= f(k[pos],b[pos],l) && f(kk,bb,r) <= f(k[pos],b[pos],r) )
     35                 return;
     36             if( l == r ) {
     37                 k[pos] = kk , b[pos] = bb;
     38                 return;
     39             }
     40             if( kk > k[pos] ) {
     41                 if( f(kk,bb,mid) > f(k[pos],b[pos],mid) ) {
     42                     update(lson[pos],l,mid,l,r,k[pos],b[pos]);
     43                     k[pos] = kk , b[pos] = bb;
     44                 }
     45                 else
     46                     update(rson[pos],mid+1,r,ll,rr,kk,bb);
     47             }
     48             else {
     49                 if( f(kk,bb,mid) > f(k[pos],b[pos],mid) ) {
     50                     update(rson[pos],mid+1,r,l,r,k[pos],b[pos]);
     51                     k[pos] = kk , b[pos] = bb;
     52                 }
     53                 else
     54                     update(lson[pos],l,mid,ll,rr,kk,bb);
     55             }
     56         }
     57         update(lson[pos],l,mid,ll,rr,kk,bb);
     58         update(rson[pos],mid+1,r,ll,rr,kk,bb);
     59     }
     60     inline lli query(int pos,int l,int r,int tar) {
     61         lli ret = f(k[pos],b[pos],tar);
     62         if( l == r )
     63             return ret;
     64         const int mid = ( l + r ) >> 1;
     65         if( tar <= mid )
     66             ret = max( ret , query(lson[pos],l,mid,tar) );
     67         else
     68             ret = max( ret , query(rson[pos],mid+1,r,tar) );
     69         return ret;
     70     }
     71 }up,down;
     72  
     73 int s[maxn],st[maxq],ed[maxq];
     74 lli k[maxq],b[maxq];
     75 int ope[maxq][4];
     76 int n,m,len=1,cnt;
     77 int v[maxn];
     78  
     79 inline lli getb(int pos,int tme,lli newk) {
     80     lli alpha = f(k[pos],b[pos],tme);
     81     return alpha - newk * srt[tme];
     82 }
     83 inline void add(int pos,int tt,lli kk,lli bb=0) {
     84     k[++cnt] = kk;
     85     if( !bb )
     86         bb = getb(s[pos],tt,kk);
     87     b[cnt] = bb;
     88     st[cnt] = tt , ed[cnt] = len;
     89     if( s[pos] )
     90         ed[s[pos]] = tt;
     91     s[pos] = cnt;
     92 }
     93  
     94 inline void init() {
     95     sort(srt+1,srt+1+len);
     96     len = unique(srt+1,srt+1+len) - srt - 1;
     97     for(int i=1;i<=m;i++)
     98         ope[i][1] = lower_bound(srt+1,srt+1+len,ope[i][1]) - srt;
     99     for(int i=1;i<=n;i++)
    100         add(i,0,0,v[i]);
    101     for(int i=1;i<=m;i++)
    102         if( *ope[i] ) {
    103             add(ope[i][2],ope[i][1],ope[i][3]);
    104         }
    105      
    106     up.build(up.cnt=1,1,len);
    107      
    108     for(int i=1;i<=cnt;i++) {
    109         up.update(1,1,len,st[i],ed[i],k[i],b[i]);
    110         down.update(1,1,len,st[i],ed[i],-k[i],-b[i]);
    111     }
    112 }
    113  
    114 inline void work() {
    115     static lli ans;
    116     for(int i=1;i<=m;i++)
    117         if( ! *ope[i] ) {
    118             ans = max( up.query(1,1,len,ope[i][1]) , down.query(1,1,len,ope[i][1]) );
    119             printf("%lld
    ",ans);
    120         }
    121 }
    122 
    123 int main() {
    124     static char com[20];
    125     scanf("%d%d",&n,&m);
    126     for(int i=1;i<=n;i++)
    127         scanf("%d",v+i);
    128     for(int i=1;i<=m;i++) {
    129         scanf("%d",&ope[i][1]);
    130         srt[++len] = ope[i][1];
    131         scanf("%s",com);
    132         if( *com == 'c' ) {
    133             ope[i][0] = 1;
    134             scanf("%d%d",&ope[i][2],&ope[i][3]);
    135         }
    136     }
    137     init();
    138     work();
    139      
    140     return 0;
    141 }
    View Code

     上面的代码是无法通过BZOJ3938的,因为少了一个return。

    BZOJ3938:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cctype>
      6 #define lli long long int
      7 #define debug cout
      8 using namespace std;
      9 const int maxn=1e5+1e2,maxq=6e5+1e2;
     10    
     11 lli srt[maxq];
     12    
     13 inline lli f(const lli &k,const lli &b,const int &x) {
     14     return k * srt[x] + b;
     15 }
     16   
     17 int lson[maxq<<3],rson[maxq<<3];
     18 struct SegmentTree {
     19     int cnt;
     20     lli k[maxq<<3],b[maxq<<3];
     21        
     22     inline void build(int pos,int ll,int rr) {
     23         if( ll == rr )
     24             return;
     25         const int mid = ( ll + rr ) >> 1;
     26         build(lson[pos]=++cnt,ll,mid);
     27         build(rson[pos]=++cnt,mid+1,rr);
     28     }
     29     inline void update(int pos,int l,int r,int ll,int rr,lli kk,lli bb) {
     30         if( rr < l || r < ll )
     31             return;
     32         const int mid = ( l + r ) >> 1;
     33         if( ll <= l && r <= rr ) {
     34             if( f(kk,bb,l) <= f(k[pos],b[pos],l) && f(kk,bb,r) <= f(k[pos],b[pos],r) )
     35                 return;
     36             if( l == r ) {
     37                 k[pos] = kk , b[pos] = bb;
     38                 return;
     39             }
     40             if( kk > k[pos] ) {
     41                 if( f(kk,bb,mid) > f(k[pos],b[pos],mid) ) {
     42                     update(lson[pos],l,mid,l,r,k[pos],b[pos]);
     43                     k[pos] = kk , b[pos] = bb;
     44                 }
     45                 else
     46                     update(rson[pos],mid+1,r,ll,rr,kk,bb);
     47             }
     48             else {
     49                 if( f(kk,bb,mid) > f(k[pos],b[pos],mid) ) {
     50                     update(rson[pos],mid+1,r,l,r,k[pos],b[pos]);
     51                     k[pos] = kk , b[pos] = bb;
     52                 }
     53                 else
     54                     update(lson[pos],l,mid,ll,rr,kk,bb);
     55             }
     56             return;
     57         }
     58         update(lson[pos],l,mid,ll,rr,kk,bb);
     59         update(rson[pos],mid+1,r,ll,rr,kk,bb);
     60     }
     61     inline lli query(int pos,int l,int r,int tar) {
     62         lli ret = f(k[pos],b[pos],tar);
     63         if( l == r )
     64             return ret;
     65         const int mid = ( l + r ) >> 1;
     66         if( tar <= mid )
     67             ret = max( ret , query(lson[pos],l,mid,tar) );
     68         else
     69             ret = max( ret , query(rson[pos],mid+1,r,tar) );
     70         return ret;
     71     }
     72 }up,down;
     73    
     74 int s[maxn],st[maxq],ed[maxq];
     75 lli k[maxq],b[maxq];
     76 int ope[maxq][4];
     77 int n,m,len=1,cnt;
     78 int v[maxn];
     79    
     80 inline lli getb(int pos,int tme,lli newk) {
     81     lli alpha = f(k[pos],b[pos],tme);
     82     return alpha - newk * srt[tme];
     83 }
     84 inline void add(int pos,int tt,lli kk,lli bb=0) {
     85     k[++cnt] = kk;
     86     if( !bb )
     87         bb = getb(s[pos],tt,kk);
     88     b[cnt] = bb;
     89     st[cnt] = tt , ed[cnt] = len;
     90     if( s[pos] )
     91         ed[s[pos]] = tt;
     92     s[pos] = cnt;
     93 }
     94    
     95 inline void init() {
     96     sort(srt+1,srt+1+len);
     97     len = unique(srt+1,srt+1+len) - srt - 1;
     98     for(int i=1;i<=m;i++)
     99         ope[i][1] = lower_bound(srt+1,srt+1+len,ope[i][1]) - srt;
    100     for(int i=1;i<=n;i++)
    101         add(i,0,0,v[i]);
    102     for(int i=1;i<=m;i++)
    103         if( *ope[i] ) {
    104             add(ope[i][2],ope[i][1],ope[i][3]);
    105         }
    106        
    107     up.build(up.cnt=1,1,len);
    108        
    109     for(int i=1;i<=cnt;i++) {
    110         up.update(1,1,len,st[i],ed[i],k[i],b[i]);
    111         down.update(1,1,len,st[i],ed[i],-k[i],-b[i]);
    112     }
    113 }
    114    
    115 inline void work() {
    116     static lli ans;
    117     for(int i=1;i<=m;i++)
    118         if( ! *ope[i] ) {
    119             ans = max( up.query(1,1,len,ope[i][1]) , down.query(1,1,len,ope[i][1]) );
    120             printf("%lld
    ",ans);
    121         }
    122 }
    123   
    124 inline int getint() {
    125     int ret = 0 , fix = 1;
    126     char ch = getchar();
    127     while( !isdigit(ch) )
    128         fix = ch == '-' ? -1 : fix,
    129         ch = getchar();
    130     while( isdigit(ch) )
    131         ret = ret * 10 + ch - '0',
    132         ch = getchar();
    133     return ret * fix;
    134 }
    135 int main() {
    136     static char com[20];
    137     n = getint() , m = getint();
    138     for(int i=1;i<=n;i++)
    139         v[i] = getint();
    140     for(int i=1;i<=m;i++) {
    141         ope[i][1] = getint();
    142         srt[++len] = ope[i][1];
    143         scanf("%s",com);
    144         if( *com == 'c' ) {
    145             ope[i][0] = 1;
    146             ope[i][2] = getint() , ope[i][3] = getint();
    147         }
    148     }
    149     init();
    150     work();
    151        
    152     return 0;
    153 }
    View Code

    对了,今天我似乎达成成就:吓跑小学妹......话说我有那么凶神恶煞吗......

  • 相关阅读:
    .net core使用NLog+Elasticsearch记录日志
    .net core使用EasyNetQ做EventBus
    .net core使用Apollo做统一配置管理
    .net core使用App.Metrics+InfluxDB+Grafana进行APM监控
    .net core使用Ocelot+Identity Server统一网关验证
    .net core微服务之基于Docker+Consul+Registrator服务注册服务发现
    windows上禁止某个软件联网
    Windows修改命令行默认启动路径
    Win10对调Esc和CapsLock键
    animation模块的使用
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8137760.html
Copyright © 2020-2023  润新知