zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    poj 2676 Suduku (dfs)
    poj 1562 Oil Deposits (dfs)
    poj 2907 Collecting Beepers (dfs)
    poj 1655 Balancing Act (树形dfs)
    poj 3411 Paid Roads (dfs)
    hdu 2896 病毒侵袭 (AC)
    hdu 3065 病毒侵袭持续中 (AC)
    poj 2251 Dungeon Master (bfs)
    java中debug使用
    Swing入门级小项目总结
  • 原文地址:https://www.cnblogs.com/idy002/p/4563611.html
Copyright © 2011-2022 走看看