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\n", query(u,v) );
204         modify(u,v,d);
205     }
206 }
View Code

 

posted @ 2015-06-09 15:11  idy002  阅读(369)  评论(0编辑  收藏  举报