P3714 [BJOI2017]树的难题 点分治+线段树合并
题目描述
分析
路径问题考虑点分治
对于一个分治中心,我们可以很容易地得到从它开始的一条路径的价值和长度
问题就是如何将不同的路径合并
很显然,对于同一个子树中的所有路径,它们起始的颜色是相同的
因此我们可以将一个节点的所有子结点按照颜色排序
这个可以在建图之前处理好
然后开两个权值线段树,一棵存储与当前节点起始颜色相同的所有路径,另一棵存储不同的所有路径
当节点的颜色改变时,把相同的那一堆合并到另一堆即可
时间复杂度 \(nlog^2n\)
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=4e5+5;
int h[maxn],tot=1,n,m,lef,rig,val[maxn];
struct asd{
int to,nxt,val;
}b[maxn];
void ad(rg int aa,rg int bb,rg int cc){
b[tot].to=bb;
b[tot].nxt=h[aa];
b[tot].val=cc;
h[aa]=tot++;
}
int siz[maxn],maxsiz[maxn],rt,totsiz;
bool vis[maxn];
void getroot(rg int now,rg int lat){
siz[now]=1,maxsiz[now]=0;
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(u==lat || vis[u]) continue;
getroot(u,now);
siz[now]+=siz[u];
maxsiz[now]=std::max(maxsiz[now],siz[u]);
}
maxsiz[now]=std::max(maxsiz[now],totsiz-siz[now]);
if(maxsiz[now]<maxsiz[rt]) rt=now;
}
struct trr{
int lch,rch,val;
trr(){
lch=rch=0;
val=-0x3f3f3f3f;//一定要初始化成无穷小
}
}tr[maxn*40];
int cnt,rt1,rt2,tp,ans=-0x3f3f3f3f;
void push_up(rg int da){
tr[da].val=std::max(tr[tr[da].lch].val,tr[tr[da].rch].val);
}
int xg(rg int da,rg int l,rg int r,rg int wz,rg int val){
if(!da){
da=++cnt;
tr[da].lch=tr[da].rch=0,tr[da].val=-0x3f3f3f3f;
}
if(l==r){
tr[da].val=std::max(tr[da].val,val);
return da;
}
rg int mids=(l+r)>>1;
if(wz<=mids) tr[da].lch=xg(tr[da].lch,l,mids,wz,val);
else tr[da].rch=xg(tr[da].rch,mids+1,r,wz,val);
push_up(da);
return da;
}
int bing(rg int aa,rg int bb,rg int l,rg int r){
if(!aa || !bb) return aa+bb;
if(l==r){
tr[aa].val=std::max(tr[aa].val,tr[bb].val);
tr[bb].val=-0x3f3f3f3f;
return aa;
}
rg int mids=(l+r)>>1;
tr[aa].lch=bing(tr[aa].lch,tr[bb].lch,l,mids);
tr[aa].rch=bing(tr[aa].rch,tr[bb].rch,mids+1,r);
push_up(aa);
return aa;
}
int cx(rg int da,rg int l,rg int r,rg int nl,rg int nr){
if(!da || l>r) return -0x3f3f3f3f;
if(l>=nl && r<=nr) return tr[da].val;
rg int mids=(l+r)>>1,nans=-0x3f3f3f3f;
if(nl<=mids) nans=std::max(nans,cx(tr[da].lch,l,mids,nl,nr));
if(nr>mids) nans=std::max(nans,cx(tr[da].rch,mids+1,r,nl,nr));
return nans;
}
struct jie{
int val,dep;
jie(){}
jie(rg int aa,rg int bb){
val=aa,dep=bb;
}
}sta[maxn];
bool cmp(rg jie aa,rg jie bb){
return aa.val>bb.val;
}
std::vector<jie> g[maxn];
void dfs(rg int now,rg int lat,rg int nval,rg int ndep,rg int latcol){
if(ndep>rig) return;
sta[++tp]=jie(nval,ndep);
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(u==lat || vis[u]) continue;
dfs(u,now,(latcol==b[i].val)?nval:nval+val[b[i].val],ndep+1,b[i].val);
}
}
void solve(rg int now){
vis[now]=1;
rt1=rt2=cnt=0;
rg int latcol=0,jud=0;
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(!vis[u]){
tp=jud=0;
dfs(u,now,val[b[i].val],1,b[i].val);
if(b[i].val==latcol) jud=1;
else {
rt1=bing(rt1,rt2,1,n);
rt2=0;
}
for(rg int j=1;j<=tp;j++){
if(jud) ans=std::max(ans,cx(rt2,1,n,std::max(1,lef-sta[j].dep),rig-sta[j].dep)+sta[j].val-val[latcol]);
ans=std::max(ans,cx(rt1,1,n,std::max(1,lef-sta[j].dep),rig-sta[j].dep)+sta[j].val);
if(sta[j].dep>=lef && sta[j].dep<=rig) ans=std::max(ans,sta[j].val);
}
for(rg int j=1;j<=tp;j++) rt2=xg(rt2,1,n,sta[j].dep,sta[j].val);
latcol=b[i].val;
}
}
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(!vis[u]){
totsiz=siz[u],rt=0;
getroot(u,now);
solve(rt);
}
}
}
int main(){
memset(h,-1,sizeof(h));
n=read(),m=read(),lef=read(),rig=read();
for(rg int i=1;i<=m;i++) val[i]=read();
rg int aa,bb,cc;
for(rg int i=1;i<n;i++){
aa=read(),bb=read(),cc=read();
g[aa].push_back(jie(cc,bb)),g[bb].push_back(jie(cc,aa));
}
for(rg int i=1;i<=n;i++) std::sort(g[i].begin(),g[i].end(),cmp);
for(rg int i=1;i<=n;i++){
for(rg int j=0;j<g[i].size();j++){
ad(i,g[i][j].dep,g[i][j].val);
}
}
maxsiz[0]=0x3f3f3f3f,rt=0,totsiz=n;
getroot(1,0);
solve(rt);
printf("%d\n",ans);
return 0;
}
P3714 [BJOI2017]树的难题 点分治+线段树合并的更多相关文章
- [BJOI2017]树的难题 点分治 线段树
题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...
- [BJOI2017]树的难题 点分治,线段树合并
[BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...
- UVALive 7148 LRIP【树分治+线段树】
题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- LOJ#6463 AK YOI 树分治+线段树合并
传送门 既然是树上路径统计问题,不难想到要使用树分治,这里以点分治为例 由点分治的性质,每层只需要考虑经过重心的路径 因为需要维护路径长度在一定范围内的最大权值和,所以要用一个数据结构维护一下到根节点 ...
- 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树
题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...
- 【BZOJ4372】烁烁的游戏 动态树分治+线段树
[BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...
- 【bzoj3730】震波 动态点分治+线段树
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
随机推荐
- AcWing 404. 婚礼
大型补档计划 题目链接 根据题意,显然只有新郎这边可能存在矛盾,考虑这边怎么放即可,新娘那边的放法与这边正好相反且一一对应. 显然对于两个约束条件是一对矛盾,开始我以为可以用并查集,后来发现输出方案的 ...
- mp4文件导致迅雷监视下载问题
原因:没有为mp4设置响应的mime Type,默认就是附件的形式. 应该为其设置mime type类型 video/mp4 <staticContent> <mimeMap fi ...
- 【Django 字段和相关参数补充】
字段类型: 1.models.AutoField 自增列=int(11) 如果没有的话,默认会生成一个名称为id的列,如果要显示的自定义一个自增列,必须将给列设置为主键primary _key=Tru ...
- 接口测试工具 Jmeter使用笔记(一:编写一个http请求)
记录学习过程 一.安装Jmeter 1.JAVA环境 JDK下载地址http://java.sun.com/javase/downloads/index.jsp 配置系统变量: (1)JAVA_HOM ...
- 【C#】DockPanelSuite 中 DockState.Document 状态下子窗体控件不显示的解决方案
DockPanelSuite 是 Winform 中优秀的布局控件,但是这次使用过程中却出了个问题. 我遇到的问题是这样的,主窗体是通过 ShowDialog 显示的,子窗体的停靠状态为 DockSt ...
- Elasticsearch 新机型发布,性能提升30%
跨年迎双节,2020 年最后一次囤货的机会来啦! Elasticsearch Service 星星海新机型发布,更高性能,更低价格. 爆款机型限时特惠,帮助您顺畅体验 Elasticsearch 云上 ...
- Spark Connector Reader 原理与实践
本文主要讲述如何利用 Spark Connector 进行 Nebula Graph 数据的读取. Spark Connector 简介 Spark Connector 是一个 Spark 的数据连接 ...
- Mybatis(一)--简介
一.JDBC问题分析: 从之前我们所写到过的jdbc代码或工具类可知: 1).数据库连接创建,释放频繁将造成系统资源浪费从而影响系统性能: 2).SQL语句在代码中硬编码,造成代码不易维护,SQL变动 ...
- Android各版本迭代改动与适配集合
前言 今天分享的面试题是: Android在版本迭代中,总会进行很多改动,那么你熟知各版本都改动了什么内容?又要怎么适配呢? Android4.4 发布ART虚拟机,提供选项可以开启. HttpURL ...
- [日常摸鱼]luogu1613跑路
新年A的第一道题2333 https://www.luogu.org/problemnew/show/P1613 题意:给一张有向图,每条边长为1,每个单位时间只能走$2^k$的长度,$k$可以任意选 ...