考虑点分治。对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化。但是注意到这里每次使用单调队列的复杂度是O(之前的子树最大深度+该子树深度),一不小心就退化成O(n2)。于是我们按照同颜色最大深度为第一关键字、子树深度为第二关键字排序,每次处理完一种颜色再与之前的其他颜色合并,这样每次的复杂度就是其自身深度了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define ll long long
#define N 200010
#define inf 2100000000
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,l,r,p[N],a[N],mxdeep[N],colordeep[N],deep[N],size[N],len[N],f[N],g[N],q[N][],Q[N],t,ans=-inf;
bool flag[N];
struct data{int to,nxt,color;
}edge[N<<];
struct data2
{
int x,y;
bool operator <(const data2&a) const
{
return colordeep[y]<colordeep[a.y]||colordeep[y]==colordeep[a.y]&&y<a.y||colordeep[y]==colordeep[a.y]&&y==a.y&&mxdeep[x]<mxdeep[a.x];
}
}v[N];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].color=z,p[x]=t;}
void make(int k,int from)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to])
{
deep[edge[i].to]=deep[k]+;
make(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
int findroot(int k,int s)
{
int mx=;
for (int i=p[k];i;i=edge[i].nxt)
if (size[edge[i].to]<size[k]&&size[edge[i].to]>size[mx]&&!flag[edge[i].to]) mx=edge[i].to;
if ((size[mx]<<)>s) return findroot(mx,s);
else return k;
}
void findmx(int k,int from,int root)
{
mxdeep[root]=max(mxdeep[root],deep[k]);
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to]) findmx(edge[i].to,k,root);
}
inline void ins(int k,int &head,int &tail,int *f){while (head<=tail&&f[Q[tail]]<f[k]) tail--;Q[++tail]=k;}
inline void pop(int k,int &head,int &tail){while (head<=tail&&Q[head]>k) head++;}
void bfs(int k,int last,int v,int d)
{
int head=,tail=;q[][]=k,q[][]=last;
int h=,t=;for (int i=min(d,r);i>=l;i--) ins(i,h,t,g);
do
{
int x=q[++head][];if (deep[x]>=l&&deep[x]<=r) ans=max(ans,len[x]);
if (deep[x]>deep[q[head-][]])
{
pop(r-deep[x],h,t);
if (l-deep[x]>=&&l-deep[x]<=d) ins(l-deep[x],h,t,g);
}
if (h<=t) ans=max(ans,len[x]+g[Q[h]]+v);
for (int i=p[x];i;i=edge[i].nxt)
if (deep[edge[i].to]>deep[x]&&!flag[edge[i].to])
{
len[edge[i].to]=len[x];
if (edge[i].color!=q[head][]) len[edge[i].to]+=a[edge[i].color];
q[++tail][]=edge[i].to,q[tail][]=edge[i].color;
}
}while (head<tail);
}
void update(int k,int from)
{
g[deep[k]]=max(g[deep[k]],len[k]);
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to]) update(edge[i].to,k);
}
void solve(int k)
{
make(k,k);k=findroot(k,size[k]);
flag[k]=;deep[k]=;make(k,k);
int cnt=;
for (int i=p[k];i;i=edge[i].nxt)
if (!flag[edge[i].to])
{
colordeep[edge[i].color]=mxdeep[edge[i].to]=,findmx(edge[i].to,edge[i].to,edge[i].to);
cnt++,v[cnt].x=edge[i].to,v[cnt].y=edge[i].color;
}
for (int i=p[k];i;i=edge[i].nxt)
if (!flag[edge[i].to]) colordeep[edge[i].color]=max(colordeep[edge[i].color],mxdeep[edge[i].to]);
sort(v+,v+cnt+);
for (int i=;i<=cnt;i++)
{
int t=i-,d=;
while (t<cnt&&v[t+].y==v[i].y)
{
len[v[++t].x]=a[v[i].y];
bfs(v[t].x,v[t].y,-a[v[i].y],d);
update(v[t].x,v[t].x);d=mxdeep[v[t].x];
}
int H=,T=;for (int j=min(colordeep[v[i-].y],r);j>=l;j--) ins(j,H,T,f);
for (int j=;j<=d;j++)
{
pop(r-j,H,T);
if (l>=j&&l-j<=d) ins(l-j,H,T,f);
if (H<=T) ans=max(ans,g[j]+f[Q[H]]);
}
for (int j=;j<=d;j++) f[j]=max(f[j],g[j]),g[j]=-inf;
i=t;
}
for (int i=;i<=mxdeep[v[cnt].x];i++) f[i]=-inf;
for (int i=p[k];i;i=edge[i].nxt)
if (!flag[edge[i].to]) solve(edge[i].to);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4860.in","r",stdin);
freopen("bzoj4860.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),l=read(),r=read();
for (int i=;i<=n;i++) f[i]=g[i]=-inf;
for (int i=;i<=m;i++) a[i]=read();
for (int i=;i<n;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z),addedge(y,x,z);
}
solve();
cout<<ans;
return ;
}

BZOJ4860 Beijing2017树的难题(点分治+单调队列)的更多相关文章

  1. BZOJ4860 BJOI2017 树的难题 点分治、线段树合并

    传送门 只会线段树……关于单调队列的解法可以去看“重建计划”一题. 看到路径长度$\in [L,R]$考虑点分治.可以知道,在当前分治中心向其他点的路径中,始边(也就是分治中心到对应子树的根的那一条边 ...

  2. [bzoj4860] [BeiJing2017]树的难题

    Description 给你一棵 n 个点的无根树.树上的每条边具有颜色. 一共有 m 种颜色,编号为 1 到 m.第 i 种颜色的权值为 ci.对于一条树上的简单路径,路径上经过的所有边按顺序组成一 ...

  3. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

  4. 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列

    题目描述 给出一棵树,定义一个点到一条路径的距离为这个点到这条路径上所有点的距离的最小值.求一条长度不超过s的路径,使得所有点到这条路径的距离的最大值最小. 输入 包含n行: 第1行,两个正整数n和s ...

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

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

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

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

  7. bzoj 4860 [BeiJing2017]树的难题

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4860 题解 点分治 设当前重心为v 假设已经把所有边按照出发点第一关键字, 颜色第二关键字排 ...

  8. luoguP3714 [BJOI2017]树的难题 点分治

    以后传数组绝对用指针... 考虑点分治 在点分的时候,把相同的颜色的在一起合并 之后,把不同颜色依次合并 我们可以用单调队列做到单次合并$O(n + m)$ 如果我们按照深度大小来合并,那么由于每次都 ...

  9. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

随机推荐

  1. Windows下MySQL多实例运行(转)

    关键字:Windows下MySQL多实例运行 阅读前注意事项: 1.有的版本的data目录不直接放在mysql安装目录下,有可能在:C:\ProgramData\MySQL\MySQL Server ...

  2. 北京Uber优步司机奖励政策(2月28日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. zookeeper的图形化展示

    1.ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供 ...

  4. Emmet 技巧

    1. Lorem 产生一段 dummy text 2. $ 变量的使用 3. 插入img的长度和宽度 使用快捷键ctrl+u插入图片的长度和宽度 注意光标要停留在图片文件名上. 其他在Sublime中 ...

  5. STM32的GUI库使用

    1. 实验平台使用百为的STM32F103开发板 2. 例程目录\百为stm32开发板光盘\stm32_gui_lib\Project\Embedded_GUI_Example\EWARM 3. 直接 ...

  6. mysql int类型的长度值

    整数类型的存储和范围(来自mysql手册) 类型 字节 最小值 最大值     (带符号的/无符号的) (带符号的/无符号的) TINYINT 1 -128 127     0 255 SMALLIN ...

  7. VMWare虚拟机下 centos network is unreachable 问题的解决

    vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=static BROADCAST=192.168.1.255 HW ...

  8. uvaoj1339 - Ancient Cipher(思维题,排序,字符串加密)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. Charles使用及mock数据

    1.下载charles 3.9.2[破解版地址:https://download.csdn.net/my] 下方有一种方法可破解4.2以前的版本 // Charles Proxy License // ...

  10. CentOS 7.2-编译安装zabbix 3.4

    起因: 前面已经使用yum安装了zabbix 3.4了,准备去交差了,交差时老大明确要求必须使用编译安装,统一放在/usr/local目录下.... 重来吧!! 一.环境说明 本次安装使用CentOS ...