洛谷题面传送门

点分治 hot tea。

首先考虑什么样的点能够对以 \(u\) 为根的答案产生 \(1\) 的贡献。我们考虑以 \(u\) 为根对整棵树进行一遍 DFS。那么对于一个点 \(v\),我们记其 \(mn_v\) 为其子树内距离其最近的叶子,\(dep_v\) 为 \(u\) 到 \(v\) 的距离,那么如果 \(mn_v\ge dep_v\),那么对于任何一个 \(v\) 子树内的叶子 \(w\),如果 Bessie 选择从 \(w\) 逃出且我们在距离 \(v\) 最近的叶子处放上一个看守者,那么在 \(v\) 处的看守者必然能够在 Bessie 到达 \(w\) 之前把 Bessie 截住。并且根据贪心的原理,只有当如果 \(v\) 的父亲 \(fa_v\) 不符合 \(mn_{fa_v}\ge dep_{fa_v}\) 时我们才会选择在距离 \(v\)​ 最近的叶子,并且这样的点必须被选,否则 \(v\) 子树内的点就堵不住了。因此一个点 \(v\) 产生条件的必要条件是 \(mn_v\ge dep_v\land mn_{fa_v}<dep_{fa_v}\)。那这是否充分了呢?或者说是否会存在某个叶子,满足两个产生贡献的点都选到这个点。答案是否定的,因为如果存在两个点 \(v_1,v_2\),满足距离它们最近的叶子相同,并且 \(mn_{v_1}\ge dep_{v_1},mn_{v_2}\ge dep_{v_2}\) 均成立,那么必然有它们的 LCA 也符合要求。因此对于一个 \(u\),满足条件的 \(v\) 的个数就是

\[\sum\limits_{v}[mn_v\ge\text{dis}(v,u)][mn_{fa_v}<\text{dis}(fa_v,u)]
\]

注意到这里涉及两个维度,如果硬要上个点分治那需要三位偏序,非常麻烦。不过注意到对于一个点,如果其满足第一个限制,那么它的子树也满足这个限制。那么怎样让每个子树的贡献都只算一次呢?考虑一个大小为 \(x\) 的子树 \(S\),由于该子树中深度最浅的节点上面还连了条边,因此该节点中所有点的度 \(d_v\) 之和等于 \(2x-1\)​,移个项可得 \(\sum\limits_{v\in S}2-d_v=1\),因此上式等价于

\[\sum\limits_{v}(2-d_v)·[mn_v\ge\text{dis}(v,u)]
\]

这东西就一脸可以点分治的样子了,考虑对于一个 \(u\) 以及一个与其不在一个分治中心儿子子树内的点 \(v\),那么记 \(dep_u\) 为 \(u\) 到分治中心的距离,那么限制可转化为 \(mn_v\ge dep_u+dep_v\),移个项可得 \(mn_v-dep_v\ge dep_u\),BIT 维护即可,时间复杂度 \(n\log^2n\)。

const int MAXN=7e4;
const int INF=0x3f3f3f3f;
int n,deg[MAXN+5],hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],ec=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int mx[MAXN+5],cent=0,siz[MAXN+5];bool vis[MAXN+5];
int mndep[MAXN+5],mnout[MAXN+5],mn[MAXN+5];
void dfs1(int x,int f){
mndep[x]=(deg[x]==1)?0:INF;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f) continue;
dfs1(y,x);chkmin(mndep[x],mndep[y]+1);
}
}
void dfs2(int x,int f){
multiset<int> st;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];
if(y==f) st.insert(mnout[x]);
else st.insert(mndep[y]+1);
}
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f) continue;
if(deg[x]==1) mnout[y]=1;
else{
st.erase(st.find(mndep[y]+1));
mnout[y]=(*st.begin())+1;
st.insert(mndep[y]+1);
} dfs2(y,x);
}
}
void findcent(int x,int f,int tot){
siz[x]=1;mx[x]=0;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f||vis[y]) continue;
findcent(y,x,tot);siz[x]+=siz[y];chkmax(mx[x],siz[y]);
} chkmax(mx[x],tot-siz[x]);
if(mx[x]<mx[cent]) cent=x;
}
int dep[MAXN+5];
void getdep(int x,int f){
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(vis[y]||y==f) continue;
dep[y]=dep[x]+1;getdep(y,x);
}
}
ll t[MAXN*2+5],res[MAXN+5];
void add(int x,int v){x+=n+1;for(int i=x;i<=(n<<1|1);i+=(i&(-i))) t[i]+=v;}
ll query(int x){x+=n+1;ll ret=0;for(int i=x;i;i&=(i-1)) ret+=t[i];return ret;}
vector<int> pt;
void getpts(int x,int f){
pt.pb(x);
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(vis[y]||y==f) continue;
getpts(y,x);
}
}
void divcent(int x){
// printf("divcent %d\n",x);
vis[x]=1;dep[x]=0;vector<int> tot;tot.pb(x);
add(mn[x]-dep[x],2-deg[x]);stack<int> stk;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(vis[y]) continue;
dep[y]=1;getdep(y,x);stk.push(y);
pt.clear();getpts(y,x);
for(int p:pt) res[p]+=query(dep[p]);
for(int p:pt) add(mn[p]-dep[p],2-deg[p]),tot.pb(p);
} for(int y:tot) add(mn[y]-dep[y],deg[y]-2);
tot.clear();
while(!stk.empty()){
int y=stk.top();stk.pop();
pt.clear();getpts(y,x);
for(int p:pt) res[p]+=query(dep[p]);
for(int p:pt) add(mn[p]-dep[p],2-deg[p]),tot.pb(p);
} res[x]+=query(dep[x]);
for(int y:tot) add(mn[y]-dep[y],deg[y]-2);
tot.clear();
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(vis[y]) continue;
cent=0;findcent(y,x,siz[y]);divcent(cent);
}
}
int main(){
// freopen("P4183_7.in","r",stdin);
scanf("%d",&n);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
adde(u,v);adde(v,u);deg[u]++;deg[v]++;
} dfs1(1,0);mnout[1]=INF;dfs2(1,0);
for(int i=1;i<=n;i++) mn[i]=min(mndep[i],mnout[i]);
// for(int i=1;i<=n;i++) printf("%d %d %d\n",mn[i],mndep[i],mnout[i]);
mx[0]=INF;findcent(1,0,n);divcent(cent);
for(int i=1;i<=n;i++) printf("%lld\n",res[i]);
return 0;
}

洛谷 P4183 - [USACO18JAN]Cow at Large P(点分治)的更多相关文章

  1. [洛谷P4183][USACO18JAN]Cow at Large P

    题目链接 Bzoj崩了之后在洛谷偶然找到的点分好题! 在暴力的角度来说,如果我们$O(n)$枚举根节点,有没有办法在$O(n)$的时间内找到答案呢? 此时如果用树形$dp$的想法,发现是可做的,因为可 ...

  2. luogu P4183 [USACO18JAN]Cow at Large P

    传送门 首先考虑N^2做法,每次从一个点出发,如果到达一个点,然后到达这个点的时间\(\le\)离这个点最近的叶子距离\(di_x\),那么答案+1,否则继续找点 这个暴力很不好优化.可以这样认为,如 ...

  3. [USACO18JAN]Cow at Large G(树形DP)

    P4186 [USACO18JAN]Cow at Large G(树形DP) Luogu4186 设dp[i]表示i点需要放多少个农民.则有 \(if(near[i]-dep[i]<=dep[i ...

  4. 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)

    LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...

  5. 洛谷5月月赛T30212 玩游戏 【分治NTT + 多项式求ln】

    题目链接 洛谷T30212 题解 式子很容易推出来,二项式定理展开后对于\(k\)的答案即可化简为如下: \[k!(\sum\limits_{i = 0}^{k} \frac{\sum\limits_ ...

  6. 洛谷 P3714 - [BJOI2017]树的难题(点分治)

    洛谷题面传送门 咦?鸽子 tzc 竟然来补题解了?incredible( 首先看到这样类似于路径统计的问题我们可以非常自然地想到点分治.每次我们找出每个连通块的重心 \(x\) 然后以 \(x\) 为 ...

  7. 洛谷 P4181 [USACO18JAN]Rental Service

    P4181 [USACO18JAN]Rental Service 题意翻译 farmer john有N(1≤N≤100,000)头牛,他想赚跟多的钱,所以他准备买牛奶和出租牛.有M(1≤M≤100,0 ...

  8. 洛谷P3611 [USACO17JAN]Cow Dance Show奶牛舞蹈

    题目描述 After several months of rehearsal, the cows are just about ready to put on their annual dance p ...

  9. 洛谷P3120 [USACO15FEB]Cow Hopscotch

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John&apos;s cows have invented ...

随机推荐

  1. Less-(26~28) preg_replace3

    Less-26: 核心语句:  各种回显均存在. 本题相比Less-25,多屏蔽了很多符号: 首先是各种注释符 --+,#,/**/  . /[]/表示字符集合:任何出现在里面的字符均会被替换. 屏蔽 ...

  2. 【UE4】虚幻引擎技术直播汇总(含中英文直播)

    B站虚幻引擎官方账号 中文直播 [中文直播]第35期 | 使用GIS在UE中创造真实地球风貌 | Epic 周澄清 [中文直播]第34期 | 包教包会的Epic MegaGrants申请之道 | Ep ...

  3. 寻找写代码感觉(八)之SpringBoot过滤器的使用

    一.什么是过滤器? 过滤器是对数据进行过滤,预处理过程,当我们访问网站时,有时候会发布一些敏感信息,发完以后有的会用*替代,还有就是登陆权限控制等,一个资源,没有经过授权,肯定是不能让用户随便访问的, ...

  4. [软工顶级理解组] 团队任务拆解(Alpha)

    一.任务概述 在alpha阶段,我们需要完成功能规格说明书中所提到的所有功能,在一个阶段的开发周期内,交付最小可行的可用版本. 二.任务分配及时长 分组&成员 具体任务 预计时长(小时) 前端 ...

  5. (数据科学学习手札129)geopandas 0.10版本重要新特性一览

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 就在前不久,我们非常熟悉的Python地理 ...

  6. linux Segmentation faults 段错误详解

    什么是段错误 下面是来自 Answers.com 的定义: A segmentation fault (often shortened to segfault) is a particular err ...

  7. C++类的静态成员变量与静态成员函数

    1.类的静态成员变量 C++类的静态成员变量主要有以下特性: 1.静态成员变量需要类内定义,类外初始化 2.静态成员变量不依赖于类,静态成员变量属于全局区,不属于类的空间. 3.静态成员变量通过类名访 ...

  8. 关于dns服务工作的原理,和配置的细节理解。

    dns服务器相关 1,dns原理,也就是迭代,和递归查询.将域名解析为ip的过程. 一次完整的查询请求经过的流程: Client -->hosts文件 -->DNS Service Loc ...

  9. shiro550反序列化分析

    拖了很久的shiro分析 漏洞概述 Apache Shiro <= 1.2.4 版本中,加密的用户信息序列化后存储在Cookie的rememberMe字段中,攻击者可以使用Shiro的AES加密 ...

  10. thread pool

    thread pool import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http ...