• bzoj 3999 线段树区间提取 有序链剖


    看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在O(nlog^3n)的时间复杂度内搞定

    这道题用到的一些方法:

      1. 可以将有关的线段提取出来,然后一起处理.

      2. 线段树可以维护两个方向的信息,这样就可以处理树上有序的东西.

      1 /**************************************************************
      2     Problem: 3999
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:3204 ms
      7     Memory:12144 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <algorithm>
     13 #define max(a,b) ((a)>(b)?(a):(b))
     14 #define N 50010
     15 using namespace std;
     16  
     17 typedef long long dnt;
     18 struct Node {
     19     dnt t, b, a[2], tag;
     20     int lf, rg;
     21     Node *ls, *rs;
     22     void pushdown() {
     23         if( tag ) {
     24             ls->t += tag;
     25             ls->b += tag;
     26             ls->tag += tag;
     27             rs->t += tag;
     28             rs->b += tag;
     29             rs->tag += tag;
     30             tag = 0;
     31         }
     32     }
     33     void update() {
     34         t = max( ls->t, rs->t );
     35         b = min( ls->b, rs->b );
     36         a[0] = max( ls->a[0], rs->a[0] );
     37         a[0] = max( a[0], rs->t-ls->b );
     38         a[1] = max( ls->a[1], rs->a[1] );
     39         a[1] = max( a[1], ls->t-rs->b );
     40     }
     41     void modify( int L, int R, int d ) {
     42         if( L<=lf && rg<=R ) {
     43             t += d;
     44             b += d;
     45             tag += d;
     46             return;
     47         }
     48         pushdown();
     49         int mid=(lf+rg)>>1;
     50         if( L<=mid ) ls->modify( L, R, d );
     51         if( R>mid ) rs->modify( L, R, d );
     52         update();
     53     }
     54 }pool[N*3], *tail=pool, *root;
     55  
     56 int n, m;
     57 int head[N], dest[N<<1], next[N<<1], etot;
     58 int aa[N], bb[N];
     59 int fat[N], dep[N], siz[N], son[N], top[N], vid[N];
     60 int qu[N], bg, ed;
     61 Node *su[N], *sv[N];
     62 int tu, tv;
     63  
     64 void adde( int u, int v ) {
     65     etot++;
     66     dest[etot] = v;
     67     next[etot] = head[u];
     68     head[u] = etot;
     69 }
     70 Node *build( int lf, int rg ) {
     71     Node *nd = ++tail;
     72     if( lf==rg ) {
     73         nd->b = nd->t = bb[lf];
     74         nd->a[0] = nd->a[1] = 0;
     75         nd->lf=lf, nd->rg=rg;
     76     } else {
     77         int mid=(lf+rg)>>1;
     78         nd->ls = build( lf, mid );
     79         nd->rs = build( mid+1, rg );
     80         nd->lf=lf, nd->rg=rg;
     81         nd->update();
     82     }
     83     return nd;
     84 }
     85 void fetch( Node *nd, int L, int R, Node *(&stk)[N], int &top ) {
     86     int lf=nd->lf, rg=nd->rg;
     87     if( L<=lf && rg<=R ) {
     88         stk[++top] = nd;
     89         return;
     90     }
     91     int mid=(lf+rg)>>1;
     92     nd->pushdown();
     93     if( R>mid ) fetch(nd->rs,L,R,stk,top);
     94     if( L<=mid ) fetch(nd->ls,L,R,stk,top);
     95 }
     96 void build_dcp( int s ) {
     97     //  fat dep
     98     fat[s] = 0;
     99     dep[s] = 1;
    100     qu[bg=ed=1] = s;
    101     while( bg<=ed ) {
    102         int u=qu[bg++];
    103         for( int t=head[u]; t; t=next[t] ) {
    104             int v=dest[t];
    105             if( v==fat[u] ) continue;
    106             fat[v] = u;
    107             dep[v] = dep[u] + 1;
    108             qu[++ed] = v;
    109         }
    110     }
    111     //  siz son
    112     for( int i=ed; i>=1; i-- ) {
    113         int u=qu[i], p=fat[u];
    114         siz[u]++;
    115         if( p ) {
    116             siz[p] += siz[u];
    117             if( siz[u]>siz[son[p]] ) son[p]=u;
    118         }
    119     }
    120     //  top vid
    121     top[s] = s;
    122     vid[s] = 1;
    123     for( int i=1; i<=ed; i++ ) {
    124         int u=qu[i];
    125         int cur=vid[u]+1;
    126         if( son[u] ) {
    127             top[son[u]] = top[u];
    128             vid[son[u]] = cur;
    129             cur += siz[son[u]];
    130         }
    131         for( int t=head[u]; t; t=next[t] ) {
    132             int v=dest[t];
    133             if( v==fat[u] || v==son[u] ) continue;
    134             top[v] = v;
    135             vid[v] = cur;
    136             cur += siz[v];
    137         }
    138     }
    139     //  segment
    140     for( int i=1; i<=n; i++ )
    141         bb[vid[i]] = aa[i];
    142     root = build( 1, n );
    143 }
    144 int lca( int u, int v ) {
    145     while( top[u]!=top[v] ) {
    146         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
    147         u = fat[top[u]];
    148     }
    149     return dep[u]<dep[v] ? u : v;
    150 }
    151 dnt query( int u, int v ) {
    152     if( u==v ) return 0;
    153     int ca = lca(u,v);
    154     tu = tv = 0;
    155     while( top[u]!=top[ca] ) {
    156         fetch(root,vid[top[u]],vid[u],su,tu);
    157         u=fat[top[u]];
    158     }
    159     while( top[v]!=top[ca] ) {
    160         fetch(root,vid[top[v]],vid[v],sv,tv);
    161         v=fat[top[v]];
    162     }
    163     if( u!=ca ) 
    164         fetch(root,vid[ca],vid[u],su,tu);
    165     else
    166         fetch(root,vid[ca],vid[v],sv,tv);
    167     dnt curt = 0;
    168     dnt rt = 0;
    169     for( int i=1; i<=tv; i++ ) {
    170         rt = max( rt, sv[i]->a[0] );
    171         rt = max( rt, curt-sv[i]->b );
    172         curt = max( curt, sv[i]->t );
    173     }
    174     for( int i=tu; i>=1; i-- ) {
    175         rt = max( rt, su[i]->a[1] );
    176         rt = max( rt, curt-su[i]->b );
    177         curt = max( curt, su[i]->t );
    178     }
    179     return rt;
    180 }
    181 void modify( int u, int v, int d ) {
    182     while( top[u]!=top[v] ) {
    183         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
    184         root->modify(vid[top[u]],vid[u],d);
    185         u=fat[top[u]];
    186     }
    187     if( dep[u]<dep[v] ) swap(u,v);
    188     root->modify(vid[v],vid[u],d);
    189 }
    190 int main() {
    191     scanf( "%d", &n );
    192     for( int i=1; i<=n; i++ )
    193         scanf( "%d", aa+i );
    194     for( int i=1,u,v; i<n; i++ ) {
    195         scanf( "%d%d", &u, &v );
    196         adde( u, v );
    197         adde( v, u );
    198     }
    199     build_dcp(1);
    200     scanf( "%d", &m );
    201     for( int t=1,u,v,d; t<=m; t++ ) {
    202         scanf( "%d%d%d", &u, &v, &d );
    203         printf( "%lld
    ", query(u,v) );
    204         modify(u,v,d);
    205     }
    206 }
    View Code
  • 相关阅读:
    【模板】线段树(区间加)
    【模板】树状数组(区间修改+单点查询)
    【模板】并查集
    【模板】最小生成树
    LOJ #10130 点的距离
    【模板】最近公共祖先(LCA)
    【模板】树状数组
    【模板】堆
    LeetCode 242 Valid Anagram
    LeetCode 171 Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/idy002/p/4563611.html
Copyright © 2020-2023  润新知