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 }