bzoj 3672 利用点分治将CDQ分治推广到树型结构上
最大的收获就是题目所说。
deal(s) : 处理节点s所在块的问题,并保证:
1、s是该块中最靠近根节点的点,没有之一。
2、s所在块到根节点的路径上的点全都用来更新过了s所在块的所有节点。
然后步骤是:
1、找s所在块的重心c。
2、如果s就是c,那么用c更新当前块的所有节点,然后“删除c”,递归处理新产生的子块。
3、否则,删除c,deal(s),用c到s的路径(不包括c,包括s)更新c除了s子块的其他子块以及c,然后再用c去更新一次。
4、递归处理其它子块。
1 #include <cstdio> 2 #include <cassert> 3 #include <cstring> 4 #include <algorithm> 5 #define N 200010 6 #define M N<<1 7 #define fill(arr,lf,rg,v) memset(arr+lf,v,sizeof(arr[0])*(rg-lf+1)) 8 using namespace std; 9 10 typedef long long dnt; 11 struct Vector { 12 dnt x, y; 13 Vector(){} 14 Vector( dnt x, dnt y ):x(x),y(y){} 15 Vector operator+( const Vector &o ) const { return Vector(x+o.x,y+o.y); } 16 Vector operator-( const Vector &o ) const { return Vector(x-o.x,y-o.y); } 17 double operator^( const Vector &o ) const { return (double)x*o.y-(double)y*o.x; } 18 }; 19 typedef Vector Point; 20 bool onleft( const Point &a, const Point &b, const Point &c ) { 21 return ((b-a)^(c-a)) >= 0.0; 22 } 23 struct Convex { 24 Point stk[N]; 25 int top; 26 void init() { 27 top=-1; 28 } 29 inline void append( const Point &p ) { 30 while( top>0 && onleft(stk[top-1],stk[top],p) ) top--; 31 stk[++top] = p; 32 } 33 const Point& query( dnt k ) { 34 int lf=0; 35 int rg=top; 36 if( lf==rg ) return stk[top]; 37 assert(k*(stk[lf].x-stk[lf+1].x)>=0); 38 if( k*(stk[lf].x-stk[lf+1].x) >= (stk[lf].y-stk[lf+1].y) ) 39 return stk[lf]; 40 assert(k*(stk[rg-1].x-stk[rg].x)>=0); 41 if( k*(stk[rg-1].x-stk[rg].x) <= (stk[rg-1].y-stk[rg].y) ) 42 return stk[rg]; 43 lf++; 44 rg--; 45 while( lf<rg ) { 46 int mid=(lf+rg)>>1; 47 assert(k*(stk[mid].x-stk[mid+1].x)>=0); 48 if( k*(stk[mid].x-stk[mid+1].x) > (stk[mid].y-stk[mid+1].y) ) 49 rg=mid; 50 else 51 lf=mid+1; 52 } 53 return stk[lf]; 54 } 55 }; 56 57 int n, case_type; 58 int head[N], next[M], dest[M], etot; 59 dnt wp[N], wq[N], lim[N], ws[M]; 60 int anc[N], fat[N], vis[N], siz[N], bac[N]; 61 dnt dep[N], dp[N]; 62 int qu[N], bg, ed; 63 Convex convex; 64 65 void adde( int u, int v, dnt s ) { 66 etot++; 67 dest[etot] = v; 68 next[etot] = head[u]; 69 ws[etot] = s; 70 head[u] = etot; 71 } 72 void bfs( int s ) { 73 qu[bg=ed=1] = s; 74 anc[s] = 0; 75 dep[s] = 0; 76 while( bg<=ed ) { 77 int u=qu[bg++]; 78 for( register int t=head[u]; t; t=next[t] ) { 79 int v=dest[t]; 80 if( v==anc[u] ) continue; 81 qu[++ed] = v; 82 anc[v] = u; 83 dep[v] = dep[u]+ws[t]; 84 } 85 } 86 } 87 int getc( int s ) { 88 qu[bg=ed=1] = s; 89 fat[s] = 0; 90 bac[s] = 0; 91 siz[s] = 0; 92 while( bg<=ed ) { 93 int u=qu[bg++]; 94 for( register int t=head[u]; t; t=next[t] ) { 95 int v=dest[t]; 96 if( vis[v] || v==fat[u] ) continue; 97 qu[++ed] = v; 98 fat[v] = u; 99 bac[v] = 0; 100 siz[v] = 0; 101 } 102 } 103 int c = 0; 104 for( register int i=ed; i>=1; i-- ) { 105 int u=qu[i]; 106 siz[u]++; 107 if( fat[u] ) { 108 int f=fat[u]; 109 siz[f]+=siz[u]; 110 if( siz[u]>bac[f] ) bac[f]=siz[u]; 111 } 112 } 113 for( register int i=1; i<=ed; i++ ) { 114 int u=qu[i]; 115 if( bac[u]<siz[s]-siz[u] ) bac[u]=siz[s]-siz[u]; 116 if( !c || bac[u]<bac[c] ) c=u; 117 } 118 //fprintf( stderr, "%d\n", c ); 119 return c; 120 } 121 void flood( int s ) { 122 qu[bg=ed=1] = s; 123 fat[s] = 0; 124 while( bg<=ed ) { 125 int u=qu[bg++]; 126 for( register int t=head[u]; t; t=next[t] ) { 127 int v=dest[t]; 128 if( vis[v] || v==fat[u] ) continue; 129 qu[++ed] = v; 130 fat[v] = u; 131 } 132 } 133 } 134 inline void update( const Point &p, int u ) { 135 dnt v = p.y + wp[u]*(dep[u]-p.x) + wq[u]; 136 if( dp[u]>v ) dp[u]=v; 137 } 138 bool cmp( int a, int b ) { 139 return dep[a]-lim[a]>dep[b]-lim[b]; 140 } 141 void vdcp( int s ) { 142 int c=getc(s); 143 vis[c] = true; 144 if( c==s ) { 145 Point pc = Point(dep[c],dp[c]); 146 flood(s); 147 for( int i=1; i<=ed; i++ ) { 148 int u=qu[i]; 149 if( u!=s && dep[u]-lim[u]<=pc.x ) update(pc,u); 150 } 151 } else { 152 vdcp(s); 153 flood(c); 154 sort( qu+1, qu+1+ed, cmp ); 155 convex.init(); 156 int cur = c; 157 for( register int i=1; i<=ed; i++ ) { 158 int u=qu[i]; 159 while( cur!=s && dep[anc[cur]]>=dep[u]-lim[u] ) { 160 cur=anc[cur]; 161 convex.append( Point(dep[cur],dp[cur]) ); 162 } 163 if( convex.top>=0 ) 164 update( convex.query(wp[u]), u ); 165 } 166 Point cp = Point(dep[c],dp[c]); 167 for( register int i=ed; i>=1; i-- ) { 168 int u=qu[i]; 169 if( u==c ) continue; 170 if( dep[u]-lim[u]>dep[c] ) break; 171 update( cp, u ); 172 } 173 } 174 for( int t=head[c]; t; t=next[t] ) { 175 int v=dest[t]; 176 if( vis[v] ) continue; 177 vdcp(v); 178 } 179 } 180 int main() { 181 scanf( "%d%d", &n, &case_type ); 182 for( int i=2; i<=n; i++ ) { 183 int f; 184 dnt s; 185 scanf( "%d%lld%lld%lld%lld", &f, &s, wp+i, wq+i, lim+i ); 186 adde( f, i, s ); 187 adde( i, f, s ); 188 } 189 fill( dp, 0, n, 0x3f ); 190 dp[1] = 0; 191 bfs(1); 192 vdcp(1); 193 for( int i=2; i<=n; i++ ) 194 printf( "%lld\n", dp[i] ); 195 }