zoukankan      html  css  js  c++  java
  • bzoj 4127 线段树维护绝对值之和

    因为d>=0,所以一个位置的数只会单调不降并且只会有一次穿过0.

    用这个性质,我们我可在线段树中记录正数负数的个数和和,以及最大的负数以及答案.

    修改操作:如果当前最大负数+d<=0,那么就直接加到懒惰标记中,否则就暴力向下传递.

    因为每个节点最多被额外访问该区间负数个数次,所以所有点总共会被额外访问O(nlogn)次,在加上修改操作和询问操作的普通访问O(mlogn)次,所以时间复杂度是有保证的.

    谢谢mhy12345的讲解.

      1 /**************************************************************
      2     Problem: 4127
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:7872 ms
      7     Memory:49256 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <vector>
     12 #include <algorithm>
     13 #define min(a,b) ((a)<(b)?(a):(b))
     14 #define max(a,b) ((a)>(b)?(a):(b))
     15 #define abs(a) ((a)<0?-(a):(a))
     16 #define oo 0x3f3f3f3f3f3f3f3fLL
     17 #define N 200010
     18 //#define fprintf(...)
     19 using namespace std;
     20  
     21 typedef long long dnt;
     22  
     23 void getn( int &v ) {
     24     char ch=getchar();
     25     bool neg = false;
     26     while( ch!='-' && (ch<'0' || ch>'9') ) ch=getchar();
     27     if( ch=='-' ) {
     28         neg = true;
     29         ch = getchar();
     30     }
     31     v = ch-'0';
     32     ch = getchar();
     33     while( '0'<=ch && ch<='9' ) {
     34         v = v*10+ch-'0';
     35         ch = getchar();
     36     }
     37     if( neg ) v=-v;
     38 }
     39  
     40 struct Node {
     41     dnt ans, sum[2], cnt[2], nmx, tag;
     42     Node *ls, *rs;
     43     inline void init( int v ) {
     44         if( v<0 ) {
     45             sum[0] = v;
     46             cnt[0] = 1;
     47             sum[1] = 0;
     48             cnt[1] = 0;
     49             ans = -v;
     50             tag = 0;
     51             nmx = v;
     52         } else {
     53             sum[0] = 0;
     54             cnt[0] = 0;
     55             sum[1] = v;
     56             cnt[1] = 1;
     57             tag = 0;
     58             ans = v;
     59             nmx = -oo;
     60         }
     61     }
     62     inline void update() {
     63         sum[0] = ls->sum[0] + rs->sum[0];
     64         sum[1] = ls->sum[1] + rs->sum[1];
     65         cnt[0] = ls->cnt[0] + rs->cnt[0];
     66         cnt[1] = ls->cnt[1] + rs->cnt[1];
     67         ans = ls->ans + rs->ans;
     68         nmx = max( ls->nmx, rs->nmx );
     69     }
     70     inline void pushdown() {
     71         if( tag ) {
     72             ls->nmx += tag;
     73             rs->nmx += tag;
     74             ls->sum[0] += ls->cnt[0]*tag;
     75             ls->sum[1] += ls->cnt[1]*tag;
     76             rs->sum[0] += rs->cnt[0]*tag;
     77             rs->sum[1] += rs->cnt[1]*tag;
     78             ls->ans = ls->sum[1]-ls->sum[0];
     79             rs->ans = rs->sum[1]-rs->sum[0];
     80             ls->tag += tag;
     81             rs->tag += tag;
     82             tag = 0;
     83         }
     84     }
     85     void modify( int lf, int rg, int L, int R, int delta ) {
     86         if( lf==rg ) {
     87             if( cnt[0] ) {
     88                 if( sum[0]+delta<=0 ) {
     89                     sum[0]+=delta;
     90                     nmx = sum[0];
     91                     ans = -sum[0];
     92                 } else {
     93                     sum[1] = sum[0]+delta;
     94                     ans = sum[1];
     95                     cnt[1] = 1;
     96                     sum[0] = cnt[0] = 0;
     97                     nmx = -oo;
     98                 }
     99             } else {
    100                 sum[1]+=delta;
    101                 ans = sum[1];
    102             }
    103             return;
    104         }
    105         if( L<=lf && rg<=R && nmx+delta<=0 ) {
    106             nmx += delta;
    107             sum[0] += cnt[0]*delta;
    108             sum[1] += cnt[1]*delta;
    109             ans = sum[1]-sum[0];
    110             tag += delta;
    111             return;
    112         }
    113         pushdown();
    114         int mid=(lf+rg)>>1;
    115         if( L<=mid ) ls->modify(lf,mid,L,R,delta);
    116         if( R>mid ) rs->modify(mid+1,rg,L,R,delta);
    117         update();
    118     }
    119     dnt query( int lf, int rg, int L, int R ) {
    120         if( L<=lf && rg<=R ) return ans;
    121         pushdown();
    122         int mid=(lf+rg)>>1;
    123         dnt rt = 0;
    124         if( L<=mid ) rt+=ls->query(lf,mid,L,R);
    125         if( R>mid ) rt+=rs->query(mid+1,rg,L,R);
    126         update();
    127         return rt;
    128     }
    129 }pool[N*3], *tail=pool, *root;
    130  
    131 int n, m;
    132 int aa[N], bb[N];
    133 int head[N], dest[N<<1], next[N<<1], etot;
    134 int fat[N], siz[N], son[N], top[N], dep[N], vid[N], qu[N], bg, ed;
    135  
    136 void adde( int u, int v ) {
    137     etot++;
    138     dest[etot] = v;
    139     next[etot] = head[u];
    140     head[u] = etot;
    141 }
    142 Node *build( int lf, int rg ) {
    143     Node *nd = ++tail;
    144     if( lf==rg) {
    145         nd->init(bb[lf]);
    146         return nd;
    147     }
    148     int mid=(lf+rg)>>1;
    149     nd->ls = build( lf, mid );
    150     nd->rs = build( mid+1, rg );
    151     nd->update();
    152     return nd;
    153 }
    154 void build_dcp( int s ) {
    155     //  fat dep
    156     fat[s] = 0;
    157     dep[s] = 1;
    158     qu[bg=ed=1] = s;
    159     while( bg<=ed ) {
    160         int u=qu[bg++];
    161         for( int t=head[u]; t; t=next[t] ) {
    162             int v=dest[t];
    163             if( v==fat[u] ) continue;
    164             fat[v] = u;
    165             dep[v] = dep[u]+1;
    166             qu[++ed] = v;
    167         }
    168     }
    169     //  siz son
    170     for( int i=ed; i>=1; i-- ) {
    171         int u=qu[i], p=fat[u];
    172         siz[u]++;
    173         if( p ) {
    174             siz[p] += siz[u];
    175             if( siz[son[p]]<siz[u] ) son[p]=u;
    176         }
    177     }
    178     //  vid top
    179     vid[s] = 1;
    180     top[s] = s;
    181     for( int i=1; i<=ed; i++ ) {
    182         int u=qu[i];
    183         int cur=vid[u]+1;
    184         if( son[u] ) {
    185             vid[son[u]] = cur;
    186             top[son[u]] = top[u];
    187             cur += siz[son[u]];
    188         }
    189         for( int t=head[u]; t; t=next[t] ) {
    190             int v=dest[t];
    191             if( v==fat[u] || v==son[u] ) continue;
    192             vid[v] = cur;
    193             top[v] = v;
    194             cur += siz[v];
    195         }
    196     }
    197     //  segment tree
    198     for( int i=1; i<=n; i++ ) 
    199         bb[vid[i]] = aa[i];
    200 //  for( int i=1; i<=n; i++ )
    201 //      fprintf( stderr, "%d ", bb[i] );
    202 //  fprintf( stderr, "
    " );
    203     root = build( 1, n );
    204 }
    205 void modify( int u, int v, int delta ) {
    206     while( top[u]!=top[v] ) {
    207         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
    208         root->modify(1,n,vid[top[u]],vid[u],delta);
    209 //      fprintf( stderr, "modify( %d %d %d )
    ", vid[top[u]], vid[u], delta );
    210         u=fat[top[u]];
    211     }
    212     if( dep[u]<dep[v] ) swap(u,v);
    213     root->modify(1,n,vid[v],vid[u],delta);
    214 //  fprintf( stderr, "modify( %d %d %d )
    ", vid[v], vid[u], delta );
    215 }
    216 dnt query( int u, int v ) {
    217     dnt rt = 0;
    218     while( top[u]!=top[v] ) {
    219         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
    220         rt += root->query(1,n,vid[top[u]],vid[u]);
    221 //      fprintf( stderr, "query( %d %d ) rt = %lld
    ", vid[top[u]], vid[u], rt );
    222         u=fat[top[u]];
    223     }
    224     if( dep[u]<dep[v] ) swap(u,v);
    225     rt += root->query(1,n,vid[v],vid[u]);
    226 //  fprintf( stderr, "query( %d %d ) rt = %lld
    ", vid[v], vid[u], rt );
    227     return rt;
    228 }
    229 int main() {
    230     getn(n); getn(m);
    231     for( int i=1; i<=n; i++ )
    232         getn(aa[i]);
    233     for( int i=1,u,v; i<n; i++ ) {
    234         getn(u); getn(v);
    235         adde( u, v );
    236         adde( v, u );
    237     }
    238     build_dcp(1);
    239     for( int t=1,opt,u,v,d; t<=m; t++ ) {
    240         getn(opt);
    241         if( opt==1 ) {
    242             getn(u);getn(v);getn(d);
    243             modify( u, v, d );
    244         } else {
    245             getn(u); getn(v);
    246             printf( "%lld
    ", query(u,v) );
    247         }
    248     }
    249 }
    View Code
  • 相关阅读:
    提升10倍生产力:IDEA远程一键部署SpringBoot到Docker
    如何写出让同事无法维护的代码?
    Nginx 极简教程(快速入门)
    实战SpringCloud响应式微服务系列教程(第一章)
    单节点nginx为两台apache服务器提供负载均衡
    监控Linux性能的18个命令行工具
    Nginx/LVS/HAProxy负载均衡软件的优缺点详解(转)
    LVS包转发模型和调度算法(转)
    借助LVS+Keepalived通过DR模式实现负载均衡
    CentOS 7.0 安装中文输入法
  • 原文地址:https://www.cnblogs.com/idy002/p/4558469.html
Copyright © 2011-2022 走看看