题解-CF348E Pilgrims
题面
有一棵 \(n\) 个点的 带权 树和 \(m\) 个关键点,要求杀了一个不关键的点,满足最多的关键点到离它最远的所有关键点的路径都被打断。求可以满足的最多关键点数和此时的杀点方案数。
数据范围:\(2\le m<n\le 10^5\)。
题解
写了个奇怪的做法调了一个上午,写篇不行的题解。
很明显所有关键点到所有离它最远的关键的所有路径都经过一个点:
距离最远的一对关键点的中点(不需要取 \(\frac{dist}{2}\) 的位置建出一个新点!如果真正的中心在边上,边上的两点都行!)。
对于每个点 \(u\),如果以它为根,离它最远的所有点的 \(\rm lca\) 为 \(v\),只有杀 \(u\) 和 \(v\) 路径上的点才能杀死 \(u\)。
所以目标就是对于每个 \(u\) 找 \(v\),然后最后树上差分就可以了。
可以以上文中的中点为根,边 dfs 边找,这个 \(v\) 是可以动态维护的。
如果当前 dfs 到节点 \(u\),这个 \(v\) 绝不会是它的子树点,甚至不可能是和 \(u\) 在根的同一棵子树内的点。
所以所有离 \(u\) 最远的点的当前 \(\rm lca\) 就是 \(v\)。
可以线段树,维护区间最大值和最大值点的 \(\rm lca\),支持区间加减。
然后就解决了。如果嫌弃 \(\Theta(\log n)\) 的 pushup,可以用 ST 表 \(\Theta(1)\) lca。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);~i;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;
//Data
const int N=1e5+1;
int n,m,rt=-1,mon[N];
bool imon[N],newed;
//Tree_0
const int D=20;
vector<int> e[N],to,we;
void adde(int u,int v,int w){
e[u].pb(sz(to)),to.pb(v),we.pb(w);
e[v].pb(sz(to)),to.pb(u),we.pb(w);
}
int dep[N],pre[N],in,dfn[N],lim[N],no[N];
int in2,dfn2[N],lg[N<<1]; pair<int,int> st[D][N<<1];
void dfs0(int u){
for(int v:e[u])if(to[v]^to[pre[u]])
dep[to[v]]=dep[u]+we[v],pre[to[v]]=v^1,dfs0(to[v]);
}
void dfs1(int u){
no[dfn[u]=in++]=u,st[0][dfn2[u]=in2++]=mp(dep[u],u);
for(int v:e[u])if(to[v]^pre[u])
dep[to[v]]=dep[pre[to[v]]=u]+we[v],dfs1(to[v]),
st[0][in2++]=mp(dep[u],u);
lim[u]=in;
}
void linit(){
R(i,D-1)R(u,in2-(2<<i)+1)
st[i+1][u]=min(st[i][u],st[i][u+(1<<i)]);
R(i,in2+1)if(i>1) lg[i]=lg[i>>1]+1;
}
int lca(int u,int v){
u=dfn2[u],v=dfn2[v];
if(u>v) swap(u,v); v++; int i=lg[v-u];
return min(st[i][u],st[i][v-(1<<i)]).y;
}
//SegmentTree
const int sN=N<<2;
#define mid ((l+r)>>1)
int mx[sN],tag[sN],anc[sN];
void pushup(int u){
if(mx[u*2+1]>mx[u*2+2]) mx[u]=mx[u*2+1],anc[u]=anc[u*2+1];
else if(mx[u*2+2]>mx[u*2+1]) mx[u]=mx[u*2+2],anc[u]=anc[u*2+2];
else mx[u]=mx[u*2+1],anc[u]=lca(anc[u*2+1],anc[u*2+2]);
}
void pushtag(int u,int v){tag[u]+=v,mx[u]+=v;}
void pushdown(int u){tag[u]&&(pushtag(u*2+1,tag[u]),
pushtag(u*2+2,tag[u]),tag[u]=0);}
void sinit(int u=0,int l=0,int r=n){
if(r-l==1) return mx[u]=imon[no[l]]?dep[no[l]]:-iinf,anc[u]=no[l],void();
sinit(u*2+1,l,mid),sinit(u*2+2,mid,r),pushup(u);
}
void fixr(int x,int y,int v,int u=0,int l=0,int r=n){
if(r<=x||y<=l) return; if(x<=l&&r<=y) return pushtag(u,v);
pushdown(u),fixr(x,y,v,u*2+1,l,mid),fixr(x,y,v,u*2+2,mid,r),pushup(u);
}
void print(int u=0,int l=0,int r=n){
if(r-l==1) return void(cout<<"["<<l<<"]:"<<mx[u]<<" ");
pushdown(u),print(u*2+1,l,mid),print(u*2+2,mid,r);
}
#undef mid
//Tree_1
int mk[N];
void dfs2(int u){
if(imon[u]) mk[u]++,mk[anc[0]]++,mk[rt]--;
for(int v:e[u])if(to[v]^pre[u]){
fixr(0,n,we[v]),fixr(dfn[to[v]],lim[to[v]],-2*we[v]);
dfs2(to[v]),fixr(0,n,-we[v]),fixr(dfn[to[v]],lim[to[v]],2*we[v]);
}
}
void dfs3(int u){
for(int v:e[u])if(to[v]^pre[u]) dfs3(to[v]),mk[u]+=mk[to[v]];
}
//Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
R(i,m) cin>>mon[i],--mon[i],imon[mon[i]]=true;
R(i,n-1){int u,v,w; cin>>u>>v>>w,--u,--v,adde(u,v,w);}
R(u,n) sort(e[u].bg,e[u].ed);
int s=-1,t=-1,now=0;
R(u,n) pre[u]=-1; dep[mon[0]]=0,dfs0(mon[0]);
R(i,m)if(!~s||dep[mon[i]]>dep[s]) s=mon[i];
R(u,n) pre[u]=-1; dep[s]=0,dfs0(s);
R(i,m)if(!~t||dep[mon[i]]>dep[t]) t=mon[i];
for(int u=t;u^s;u=to[pre[u]]){
if(now>=dep[t]/2){rt=u;break;}
now+=we[pre[u]];
}
if(!~rt) rt=s;
R(u,n) pre[u]=-1;
dep[rt]=0,dfs1(rt),linit(),sinit(),dfs2(rt),dfs3(rt);
int mx=-1,cnt=0;
R(u,n)if(!imon[u]){
if(mk[u]>mx) mx=mk[u],cnt=1;
else if(mk[u]==mx) cnt++;
}
cout<<mx<<" "<<cnt<<'\n';
return 0;
}
祝大家学习愉快!
题解-CF348E Pilgrims的更多相关文章
- Codeforces-348E Pilgrims
#4342. CF348 Pilgrims 此题同UOJ#11 ydc的大树 Online Judge:Bzoj-4342,Codeforces-348E,Luogu-CF348E,Uoj-#11 L ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
随机推荐
- 删除ceph集群mds
ceph集群新搭建以后是只有一个默认的存储池rbd的池 ## 创建文件接口集群 1.创建一个元数据池 [root@mytest ~]# ceph osd pool create metadata 20 ...
- Vue知识点回顾(一)
一.什么是vue? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不 ...
- 消灭又臭又长的if-else
背景 由于目前工作岗位的原因,项目还是09年建立的,历史遗留问题也比较多,加上开发规范并不是很完善,项目中有的单个方法达到成百上千行,if-else更是连续写十几个也不累. 作为强迫症真的受不了,另一 ...
- 万字长文!从底层开始带你了解并发编程,彻底帮你搞懂java锁!
线程是否要锁住同步资源 锁住 悲观锁 不锁住 乐观锁 锁住同步资源失败 线程是否要阻塞 阻塞 不阻塞自旋锁,适应性自旋锁 多个线程竞争同步资源的流程细节有没有区别 不锁住资源,多个线程只有一个能修改资 ...
- django清理migration终极解决办法
1.django生成数据表结构的过程 在我们设计好models以后,我们可以通过以下命令生成将要同步给数据库的数据结构文件 python manage.py makemigrations 生成的文件在 ...
- swupdate实例
平台:imx8mm 系统:linux 4.4 如果需要系统了解swupdate,请参考文章:嵌入式系统更新swupdate分类 一.制作升级包 emmcsetup.lua用来描述update执 ...
- Mac下载工具folx如何下载常用的软件
最近,多档综艺节目都开展得如火如荼,比如<中国新说唱>.<这就是街舞>等深受年轻人喜欢的综艺节目.虽然手机端也可观看,但可以的话,当然是使用电脑屏幕观看节目比较过瘾. 接下来, ...
- 详细了解IDM的队列功能
队列的种类 IDM(Internet Download Manager)下载器的队列分为2种:主要下载队列和同步队列.此外,我们也可以自己创建附加队列. 在左边的[分类]窗口中,黄色的图标为主要下载队 ...
- guitar pro系列教程(一):Guitar Pro主界面之记谱功能的详细解析【上】
相信弹吉他的朋友们对guitar pro这款软件并不陌生,也有很多朋友用它来看谱制谱.而GP有很多实用功能,能够使我们看谱更清晰,制谱更便捷,所以让我们一起来看看吧 Guitar Pro对初学作曲,特 ...
- 接上一篇:(二) IOC的概念和作用
IOC的概念和作用 控制反转(IoC:Inversion of Control)把创建对象的权利转交给框架(框架的重要特征),并非面向对象的专用术语. 它包含依赖注入(DI:Dependency In ...