感谢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. 点分不擅长求全局最...的东西,而是擅长关于某个点....的东西.

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

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

 #include <cstdio>
#include <vector>
#include <map>
#define max(a,b) ((a)>(b)?(a):(b))
#define oo 0x3f3f3f3f3f3f3f3fLL
#define N 100010
#define M N<<1
#define P 17
using namespace std; typedef long long dnt;
struct Info {
int p, s;
Info(){}
Info( int p, int s ):p(p),s(s){}
};
struct Pair {
int s, c;
Pair(){}
Pair( int s, int c ):s(s),c(c){}
}; int n, m;
int head[N], dest[M], wght[M], next[M], etot;
int idv[M], vid[N], dep[N], stu[M][P+], stp[M][P+];
int bac[N], fat[N], siz[N], vis[N], dis[N];
int bin[P+], log[M], qu[N], bg, ed;
//Info info[N][P+1]; int icnt[N];
//Pair gc[N][22]; int gcnt[N];
vector<Info> info[N];
vector<Pair> gc[N];
dnt cans[N], fans[N], sumw[N];
dnt rans[N]; int tag[N], curt; inline void uMax( int &u, int v ) { if( u<v ) u=v; }
void adde( int u, int v, int w ) {
etot++;
dest[etot] = v;
wght[etot] = w;
next[etot] = head[u];
head[u] = etot;
}
void build_lca( int s ) {
// qu fat dep dis, siz
fat[s] = ;
dep[s] = ;
dis[s] = ;
siz[s] = ;
qu[bg=ed=] = s;
while( bg<=ed ) {
int u=qu[bg++];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t], w=wght[t];
if( v==fat[u] ) continue;
fat[v] = u;
siz[v] = ;
dep[v] = dep[u]+;
dis[v] = dis[u]+w;
qu[++ed] = v;
}
}
// siz
for( register int i=ed; i>=; i-- ) {
int u=qu[i], p=fat[u];
siz[u]++;
siz[p]+=siz[u];
}
siz[s]++;
// idv vid
vid[s] = ;
idv[] = s;
for( register int i=; i<=ed; i++ ) {
int u=qu[i];
int cur=vid[u]+;
for( register int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] ) continue;
idv[cur] = u;
cur++;
vid[v] = cur;
idv[cur] = v;
cur += siz[v]+siz[v]-;
}
}
idv[n+n] = s;
// bin log
int idc = n+n;
bin[] = ;
for( int i=; i<=P; i++ ) bin[i] = bin[i-]<<;
log[] = -;
for( int i=; i<=idc; i++ ) log[i] = log[i>>]+;
// stu stp
for( int i=; i<=idc; i++ ) {
stu[i][] = idv[i];
stp[i][] = dep[idv[i]];
}
for( int p=; p<=log[idc]; p++ ) {
for( register int i=; i<=idc-bin[p]+; i++ ) {
if( stp[i][p-] < stp[i+bin[p-]][p-] ) {
stp[i][p] = stp[i][p-];
stu[i][p] = stu[i][p-];
} else {
stp[i][p] = stp[i+bin[p-]][p-];
stu[i][p] = stu[i+bin[p-]][p-];
}
}
}
}
inline int lca( int u, int v ) {
int lf=vid[u], rg=vid[v];
if( lf>rg ) swap(lf,rg);
int p = log[rg-lf+];
if( stp[lf][p] < stp[rg-bin[p]+][p] )
return stu[lf][p];
else
return stu[rg-bin[p]+][p];
}
inline int qu_dis( int u, int v ) {
int ca = lca(u,v);
return dis[u]+dis[v]-(dis[ca]<<);
}
int build_vdcp( int s ) {
int c;
// qu fat, siz bac
fat[s] = ;
siz[s] = bac[s] = ;
qu[bg=ed=] = s;
while( bg<=ed ) {
int u=qu[bg++];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] || vis[v] ) continue;
fat[v] = u;
siz[v] = bac[v] = ;
qu[++ed] = v;
}
}
// siz bac
for( register int i=ed; i>=; i-- ) {
int u=qu[i], p=fat[u];
siz[u]++;
siz[p]+=siz[u];
uMax( bac[p], siz[u] );
}
siz[s]++;
// bac c
c = ;
for( register int i=; i<=ed; i++ ) {
int u=qu[i];
uMax( bac[u], siz[s]-siz[u] );
if( bac[u]<bac[c] ) c=u;
}
// qu info
vis[c] = true;
vector<int> stk;
for( int t=head[c]; t; t=next[t] ) {
int s=dest[t], cc;
if( vis[s] ) continue; qu[bg=ed=] = s;
fat[s] = c;
stk.clear();
while( bg<=ed ) {
int u=qu[bg++];
stk.push_back( u );
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] || vis[v] ) continue;
qu[++ed] = v;
fat[v] = u;
}
}
cc = build_vdcp(s);
gc[c].push_back(Pair(s,cc));
// gc[c][gcnt[c]] = Pair(s,cc);
// gcnt[c]++;
for( register int t=stk.size()-; t>=; t-- ) {
int u=stk[t];
info[u].push_back( Info(c,cc) );
// info[u][icnt[u]] = Info(c,cc);
// icnt[u]++;
}
}
return c;
}
dnt query( int u ) {
if( tag[u]==curt ) return rans[u];
tag[u] = curt;
dnt rt = cans[u];
for( int t=; t<info[u].size(); t++ ) {
// for( int t=icnt[u]-1; t>=0; t-- ) {
int p=info[u][t].p, s=info[u][t].s;
rt += cans[p]-fans[s]+(sumw[p]-sumw[s])*qu_dis(u,p);
}
return rans[u]=rt;
}
dnt search( int u ) {
dnt su = query(u);
for( int t=; t<gc[u].size(); t++ ) {
// for( int t=gcnt[u]-1; t>=0; t-- ) {
Pair &p = gc[u][t];
dnt a=query(p.s);
if( a<su ) return search(p.c);
}
return su;
}
void modify( int u, int delta ) {
sumw[u] += delta;
for( int t=info[u].size()-; t>=; t-- ) {
// for( int t=icnt[u]-1; t>=0; t-- ) {
int p=info[u][t].p, s=info[u][t].s;
dnt d = (dnt)delta*qu_dis(u,p);
cans[p] += d;
fans[s] += d;
sumw[p] += delta;
}
}
int main() {
scanf( "%d%d", &n, &m );
for( int i=,u,v,w; i<n; i++ ) {
scanf( "%d%d%d", &u, &v, &w );
adde( u, v, w );
adde( v, u, w );
}
bac[] = n;
int core = build_vdcp();
build_lca();
for( int t=,u,d; t<=m; t++ ) {
scanf( "%d%d", &u, &d );
modify( u, d );
curt = t;
printf( "%lld\n", search(core) );
}
}

bzoj 3924 点分的更多相关文章

  1. [BZOJ 4332] [JSOI2012]分零食(DP+FFT)

    [BZOJ 4332] [JSOI2012]分零食(DP+FFT) 题面 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\ ...

  2. BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)

    题意 树的结构不变,每个点有点权,每一条边有边权,有修改点权的操作,设xxx为树中一点.求∑idist(x,i)∗a[i]\sum_idist(x,i)*a[i]i∑​dist(x,i)∗a[i]的最 ...

  3. bzoj 3924 [Zjoi2015]幻想乡战略游戏——动态点分治(暴力移动找重心)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 度数只有20,所以从一个点暴力枚举其出边,就能知道往哪个方向走. 知道方向之后直接走到 ...

  4. BZOJ 4710: [Jsoi2011]分特产 [容斥原理]

    4710: [Jsoi2011]分特产 题意:m种物品分给n个同学,每个同学至少有一个物品,求方案数 对于每种物品是独立的,就是分成n组可以为空,然后可以用乘法原理合起来 容斥容斥 \[ 每个同学至少 ...

  5. bzoj 3924: [Zjoi2015]幻想乡战略游戏

    Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...

  6. ●BZOJ 4710 [Jsoi2011]分特产

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4710 题解: 容斥,组合先看看这个方案数的计算:把 M 个相同的东西分给 N 个人,每个人可 ...

  7. bzoj 4710: [Jsoi2011]分特产

    Description JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望 ...

  8. 【BZOJ 3924】[Zjoi2015]幻想乡战略游戏

    题目: 题解: 对点分树理解加深了233,膜拜zzh干翻紫荆花. 感谢zzh的讲解. 首先优化基于传统DP,假设树不发生变化,我们就可以利用DP求出带权重心. 考虑修改,我们思路不变,还是从root开 ...

  9. bzoj 4332: JSOI2012 分零食 快速傅立叶变换

    题目: Description 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\(f(x)=O*x^2+S*x+U\) 现 ...

随机推荐

  1. Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列

    Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列   前台传来的字符串:'589,321' SELECT*FROM TAB_A T1 WHERE  T1.CODE  IN ( SEL ...

  2. Project Euler Problem7

    10001st prime Problem 7 By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see t ...

  3. Vue项目之背景图片打包后路径错误

    第一种方法: 原因: 首先,出错点在url-loader上面. // url-loader配置 // build/webpck.base.conf.js { test: /\.(png|jpe?g|g ...

  4. 用Python实现Excel的读写

    一.读excel文件的简单示例 #!/usr/bin/env python # -*- coding:utf-8 -*- import xlrd from xlrd.book import Book ...

  5. hdu1423LCIS zoj2432 必须掌握!

    LCIS就是最长上升公共子序列,要结合LIS和LCS来求 LIS:f[j]=max(f[i])+1; LCS:f[i,j]=max(f[i-1,j],f[i,j-1]或f[i-1,j-1]+1 那么对 ...

  6. 通配符(WildCard)的使用

    一.关于WildCard:一个web应用,有成千上万个action声明,可以利用struts2提供的映射机制把多个彼此相似的映射关系简化成一个映射关系,即通配符. 1.新建类 ActionWildCa ...

  7. django项目验证码(PIL库实现)

    作个记录,这个东东,是可以到处照搬的. WINDOWS下和LINUX下,字体对象获取方式不一样. 为了用户体验,字体大小也重要的. 另外,为了照顾个别字母认不出来的人,提供刷新功能. 一,验证码函数 ...

  8. 解决Delphi7的自带的UTF-8编码转换函数BUG

    Delphi7及其以下版本的 VCL 只支持 Ansi, 所以... WideString 与 UTF8String (定义与 AnsiString 相同) 并没有办法正确的在 VCL 中显示 Del ...

  9. Shell命令 中|| &&使用

    转自:https://www.cnblogs.com/aaronLinux/p/8340281.html

  10. ubuntu server 18.04 lts 终端中文显示为乱码的解决方案

    .最近安装ubuntu server 18.04 lts版本发现系统自带的终端下无论是编辑中文,还是显示中文均出现乱码,还是老毛病, 今天无意中发现通过ssh,远程访问,在windows中安装开源的p ...