zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", dp[i] );
    195 }
    View Code
  • 相关阅读:
    codna的安装与使用
    ubuntu 下修改MySQL 的root用户密码
    python中的排序
    CF 543C Remembering Strings
    CF 1119C Ramesses and Corner Inversion
    HihoCoder 1384 Genius ACM
    BZOJ3032 七夕祭
    Vjudge Code
    CF51C Three Base Stations
    Sumdiv POJ 1845
  • 原文地址:https://www.cnblogs.com/idy002/p/4507965.html
Copyright © 2011-2022 走看看