题目描述

题目传送门

分析

路径问题考虑点分治

对于一个分治中心,我们可以很容易地得到从它开始的一条路径的价值和长度

问题就是如何将不同的路径合并

很显然,对于同一个子树中的所有路径,它们起始的颜色是相同的

因此我们可以将一个节点的所有子结点按照颜色排序

这个可以在建图之前处理好

然后开两个权值线段树,一棵存储与当前节点起始颜色相同的所有路径,另一棵存储不同的所有路径

当节点的颜色改变时,把相同的那一堆合并到另一堆即可

时间复杂度 \(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]树的难题 点分治+线段树合并的更多相关文章

  1. [BJOI2017]树的难题 点分治 线段树

    题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...

  2. [BJOI2017]树的难题 点分治,线段树合并

    [BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...

  3. UVALive 7148 LRIP【树分治+线段树】

    题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...

  4. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  5. LOJ#6463 AK YOI 树分治+线段树合并

    传送门 既然是树上路径统计问题,不难想到要使用树分治,这里以点分治为例 由点分治的性质,每层只需要考虑经过重心的路径 因为需要维护路径长度在一定范围内的最大权值和,所以要用一个数据结构维护一下到根节点 ...

  6. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  7. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...

  8. 【bzoj4372】烁烁的游戏 动态点分治+线段树

    题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...

  9. 【bzoj3730】震波 动态点分治+线段树

    题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...

随机推荐

  1. AcWing 404. 婚礼

    大型补档计划 题目链接 根据题意,显然只有新郎这边可能存在矛盾,考虑这边怎么放即可,新娘那边的放法与这边正好相反且一一对应. 显然对于两个约束条件是一对矛盾,开始我以为可以用并查集,后来发现输出方案的 ...

  2. mp4文件导致迅雷监视下载问题

    原因:没有为mp4设置响应的mime Type,默认就是附件的形式. 应该为其设置mime type类型  video/mp4 <staticContent> <mimeMap fi ...

  3. 【Django 字段和相关参数补充】

    字段类型: 1.models.AutoField 自增列=int(11) 如果没有的话,默认会生成一个名称为id的列,如果要显示的自定义一个自增列,必须将给列设置为主键primary _key=Tru ...

  4. 接口测试工具 Jmeter使用笔记(一:编写一个http请求)

    记录学习过程 一.安装Jmeter 1.JAVA环境 JDK下载地址http://java.sun.com/javase/downloads/index.jsp 配置系统变量: (1)JAVA_HOM ...

  5. 【C#】DockPanelSuite 中 DockState.Document 状态下子窗体控件不显示的解决方案

    DockPanelSuite 是 Winform 中优秀的布局控件,但是这次使用过程中却出了个问题. 我遇到的问题是这样的,主窗体是通过 ShowDialog 显示的,子窗体的停靠状态为 DockSt ...

  6. Elasticsearch 新机型发布,性能提升30%

    跨年迎双节,2020 年最后一次囤货的机会来啦! Elasticsearch Service 星星海新机型发布,更高性能,更低价格. 爆款机型限时特惠,帮助您顺畅体验 Elasticsearch 云上 ...

  7. Spark Connector Reader 原理与实践

    本文主要讲述如何利用 Spark Connector 进行 Nebula Graph 数据的读取. Spark Connector 简介 Spark Connector 是一个 Spark 的数据连接 ...

  8. Mybatis(一)--简介

    一.JDBC问题分析: 从之前我们所写到过的jdbc代码或工具类可知: 1).数据库连接创建,释放频繁将造成系统资源浪费从而影响系统性能: 2).SQL语句在代码中硬编码,造成代码不易维护,SQL变动 ...

  9. Android各版本迭代改动与适配集合

    前言 今天分享的面试题是: Android在版本迭代中,总会进行很多改动,那么你熟知各版本都改动了什么内容?又要怎么适配呢? Android4.4 发布ART虚拟机,提供选项可以开启. HttpURL ...

  10. [日常摸鱼]luogu1613跑路

    新年A的第一道题2333 https://www.luogu.org/problemnew/show/P1613 题意:给一张有向图,每条边长为1,每个单位时间只能走$2^k$的长度,$k$可以任意选 ...