bzoj 3924 点分

 

感谢asm.Definer清楚明了的题解:

http://www.cnblogs.com/Asm-Definer/p/4470112.html

 

收获:

  1.  关于重心, 对于一个无向图, 我们这样给每条边重新确定方向: u<->v这条边将原图分成两个部分Su,Sv,w(S)表示S集合中点的权值和,那么

     u->v 当 w(Su)<w(Sv)

     u<-v 当 w(Su)>w(Sv)

     u<->v 当 w(Su)=w(Sv)

     那么从一个点沿着边的方向走,直到走到一个区域,使得走不出这个区域,那么这个区域中的任何一个点就是重心.

  2. 有了第一条,就可以运用点分来搞一些询问某个点的的东西了(这里就是询问以这个点为重心的权和).

    再用点分最多log层和类似1的性质,就可以做了.

  3. 点分不擅长求全局最...的东西,而是擅长关于某个点....的东西.

    这道题可以用是因为有重心位置的单调性.

    还有捉迷藏那道题是用堆来辅助的.

  1 #include <cstdio>
  2 #include <vector>
  3 #include <map>
  4 #define max(a,b) ((a)>(b)?(a):(b))
  5 #define oo 0x3f3f3f3f3f3f3f3fLL
  6 #define N 100010
  7 #define M N<<1
  8 #define P 17
  9 using namespace std;
 10 
 11 typedef long long dnt;
 12 struct Info {
 13     int p, s;
 14     Info(){}
 15     Info( int p, int s ):p(p),s(s){}
 16 };
 17 struct Pair {
 18     int s, c;
 19     Pair(){}
 20     Pair( int s, int c ):s(s),c(c){}
 21 };
 22 
 23 int n, m;
 24 int head[N], dest[M], wght[M], next[M], etot;
 25 int idv[M], vid[N], dep[N], stu[M][P+1], stp[M][P+1];
 26 int bac[N], fat[N], siz[N], vis[N], dis[N];
 27 int bin[P+1], log[M], qu[N], bg, ed;
 28 //Info info[N][P+1]; int icnt[N];
 29 //Pair gc[N][22]; int gcnt[N];
 30 vector<Info> info[N];
 31 vector<Pair> gc[N];
 32 dnt cans[N], fans[N], sumw[N];
 33 dnt rans[N]; int tag[N], curt;
 34 
 35 inline void uMax( int &u, int v ) { if( u<v ) u=v; }
 36 void adde( int u, int v, int w ) {
 37     etot++;
 38     dest[etot] = v;
 39     wght[etot] = w;
 40     next[etot] = head[u];
 41     head[u] = etot;
 42 }
 43 void build_lca( int s ) {
 44     //    qu fat dep dis, siz
 45     fat[s] = 0;
 46     dep[s] = 1;
 47     dis[s] = 0;
 48     siz[s] = 0;
 49     qu[bg=ed=1] = s;
 50     while( bg<=ed ) {
 51         int u=qu[bg++];
 52         for( int t=head[u]; t; t=next[t] ) {
 53             int v=dest[t], w=wght[t];
 54             if( v==fat[u] ) continue;
 55             fat[v] = u;
 56             siz[v] = 0;
 57             dep[v] = dep[u]+1;
 58             dis[v] = dis[u]+w;
 59             qu[++ed] = v;
 60         }
 61     }
 62     //    siz
 63     for( register int i=ed; i>=2; i-- ) {
 64         int u=qu[i], p=fat[u];
 65         siz[u]++;
 66         siz[p]+=siz[u];
 67     }
 68     siz[s]++;
 69     //    idv vid
 70     vid[s] = 1;
 71     idv[1] = s;
 72     for( register int i=1; i<=ed; i++ ) {
 73         int u=qu[i];
 74         int cur=vid[u]+1;
 75         for( register int t=head[u]; t; t=next[t] ) {
 76             int v=dest[t];
 77             if( v==fat[u] ) continue;
 78             idv[cur] = u;
 79             cur++;
 80             vid[v] = cur;
 81             idv[cur] = v;
 82             cur += siz[v]+siz[v]-1;
 83         }
 84     }
 85     idv[n+n] = s;
 86     //    bin log
 87     int idc = n+n;
 88     bin[0] = 1;
 89     for( int i=1; i<=P; i++ ) bin[i] = bin[i-1]<<1;
 90     log[0] = -1;
 91     for( int i=1; i<=idc; i++ ) log[i] = log[i>>1]+1;
 92     //    stu stp
 93     for( int i=1; i<=idc; i++ ) {
 94         stu[i][0] = idv[i];
 95         stp[i][0] = dep[idv[i]];
 96     }
 97     for( int p=1; p<=log[idc]; p++ ) {
 98         for( register int i=1; i<=idc-bin[p]+1; i++ ) {
 99             if( stp[i][p-1] < stp[i+bin[p-1]][p-1] ) {
100                 stp[i][p] = stp[i][p-1];
101                 stu[i][p] = stu[i][p-1];
102             } else {
103                 stp[i][p] = stp[i+bin[p-1]][p-1];
104                 stu[i][p] = stu[i+bin[p-1]][p-1];
105             }
106         }
107     }
108 }
109 inline int lca( int u, int v ) {
110     int lf=vid[u], rg=vid[v];
111     if( lf>rg ) swap(lf,rg);
112     int p = log[rg-lf+1];
113     if( stp[lf][p] < stp[rg-bin[p]+1][p] )
114         return stu[lf][p];
115     else
116         return stu[rg-bin[p]+1][p];
117 }
118 inline int qu_dis( int u, int v ) {
119     int ca = lca(u,v);
120     return dis[u]+dis[v]-(dis[ca]<<1);
121 }
122 int build_vdcp( int s ) {
123     int c;
124     //    qu fat, siz bac
125     fat[s] = 0;
126     siz[s] = bac[s] = 0;
127     qu[bg=ed=1] = s;
128     while( bg<=ed ) {
129         int u=qu[bg++];
130         for( int t=head[u]; t; t=next[t] ) {
131             int v=dest[t];
132             if( v==fat[u] || vis[v] ) continue;
133             fat[v] = u;
134             siz[v] = bac[v] = 0;
135             qu[++ed] = v;
136         }
137     }
138     //    siz bac
139     for( register int i=ed; i>=2; i-- ) {
140         int u=qu[i], p=fat[u];
141         siz[u]++;
142         siz[p]+=siz[u];
143         uMax( bac[p], siz[u] );
144     }
145     siz[s]++;
146     //    bac c
147     c = 0;
148     for( register int i=1; i<=ed; i++ ) {
149         int u=qu[i];
150         uMax( bac[u], siz[s]-siz[u] );
151         if( bac[u]<bac[c] ) c=u;
152     }
153     //    qu info
154     vis[c] = true;
155     vector<int> stk;
156     for( int t=head[c]; t; t=next[t] ) {
157         int s=dest[t], cc;
158         if( vis[s] ) continue;
159 
160         qu[bg=ed=1] = s;
161         fat[s] = c;
162         stk.clear();
163         while( bg<=ed ) {
164             int u=qu[bg++];
165             stk.push_back( u );
166             for( int t=head[u]; t; t=next[t] ) {
167                 int v=dest[t];
168                 if( v==fat[u] || vis[v] ) continue;
169                 qu[++ed] = v;
170                 fat[v] = u;
171             }
172         }
173         cc = build_vdcp(s);
174         gc[c].push_back(Pair(s,cc));
175 //        gc[c][gcnt[c]] = Pair(s,cc);
176 //        gcnt[c]++;
177         for( register int t=stk.size()-1; t>=0; t-- )  {
178             int u=stk[t];
179             info[u].push_back( Info(c,cc) );
180 //            info[u][icnt[u]] = Info(c,cc);
181 //            icnt[u]++;
182         }
183     }
184     return c;
185 }
186 dnt query( int u ) {
187     if( tag[u]==curt ) return rans[u];
188     tag[u] = curt;
189     dnt rt = cans[u];
190     for( int t=0; t<info[u].size(); t++ ) {
191 //    for( int t=icnt[u]-1; t>=0; t-- ) {
192         int p=info[u][t].p, s=info[u][t].s;
193         rt += cans[p]-fans[s]+(sumw[p]-sumw[s])*qu_dis(u,p);
194     }
195     return rans[u]=rt;
196 }
197 dnt search( int u ) {
198     dnt su = query(u);
199     for( int t=0; t<gc[u].size(); t++ ) {
200 //    for( int t=gcnt[u]-1; t>=0; t-- ) {
201         Pair &p = gc[u][t];
202         dnt a=query(p.s);
203         if( a<su ) return search(p.c);
204     }
205     return su;
206 }
207 void modify( int u, int delta ) {
208     sumw[u] += delta;
209     for( int t=info[u].size()-1; t>=0; t-- ) {
210 //    for( int t=icnt[u]-1; t>=0; t-- ) {
211         int p=info[u][t].p, s=info[u][t].s;
212         dnt d = (dnt)delta*qu_dis(u,p);
213         cans[p] += d;
214         fans[s] += d;
215         sumw[p] += delta;
216     }
217 }
218 int main() {
219     scanf( "%d%d", &n, &m );
220     for( int i=1,u,v,w; i<n; i++ ) {
221         scanf( "%d%d%d", &u, &v, &w );
222         adde( u, v, w );
223         adde( v, u, w );
224     }
225     bac[0] = n;
226     int core = build_vdcp(1);
227     build_lca(1);
228     for( int t=1,u,d; t<=m; t++ ) {
229         scanf( "%d%d", &u, &d );
230         modify( u, d );
231         curt = t;
232         printf( "%lld\n", search(core) );
233     }
234 }
View Code

 

posted @ 2015-06-17 20:50 idy002 阅读(...) 评论(...) 编辑 收藏