[bzoj4860] [BeiJing2017]树的难题
Description
给你一棵 n 个点的无根树。树上的每条边具有颜色。 一共有 m 种颜色,编号为 1 到 m。第 i 种颜色的权值为
ci。对于一条树上的简单路径,路径上经过的所有边按顺序组成一个颜色序列,序列可以划分成若干个相同颜色段
。 定义路径权值为颜色序列上每个同颜色段的颜色权值之和。请你计算,经过边数在 l 到 r 之间的所有简单路
径中, 路径权值的最大值。
Input
第一行, 四个整数 n, m, l, r。
第二行, n 个整数 c1, c2, ……, cm,由空格隔开。依次表示每个颜色的权值。
接下来 n-1 行,每行三个整数 u, v, c,表示点 u 和点 v 之间有一条颜色为 c 的边。
Output
输出一行, 一个整数, 表示答案。
Sample Input
5 3 1 4
-1 -5 -2
1 2 1
1 3 1
2 4 2
2 5 3
Sample Output
-1
Solution
统计链上信息,上点分治。
对于当前的分治中心,把边按颜色\(sort\)一遍,然后开两个线段树,对于颜色相同的边用一颗线段树统计,不同的也开一颗,做完一种颜色就把两颗线段树合并一下,然后清空就好了。
复杂度\(O(n\log^2n)\),然后凭借信仰过掉此题(跑的还蛮快的)
不过正解好像是单调队列,我太弱了不会QAQ
#include<bits/stdc++.h>
using namespace std;
inline int max(int x,int y) {return x>y?x:y;}
#define il inline
il void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
il void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
il void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
const int maxn = 6e5+10;
const int inf = 1e9;
int n,m,l,r,tot,st[maxn],ed[maxn],ls[maxn<<2],rs[maxn<<2],tr[maxn<<2],cnt;
struct edge{
int fr,to,w;
int operator < (const edge &rhs) const {
return fr<rhs.fr||(fr==rhs.fr&&w<rhs.w);
}
}e[maxn<<1];
il void add(int u,int v,int w) {e[++tot]=(edge){u,v,w};}
il void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}
#define mid ((l+r)>>1)
namespace Segment_Tree {
void modify(int &p,int l,int r,int x,int v) {
if(!p) p=++cnt,ls[p]=rs[p]=0,tr[p]=-inf;
else tr[p]=max(tr[p],v);
if(l==r) return ;
if(x<=mid) modify(ls[p],l,mid,x,v);
else modify(rs[p],mid+1,r,x,v);
}
int query(int p,int l,int r,int x,int y) {
if(!p) return -inf;
if(x<=l&&r<=y) return tr[p];
int ans=-inf;
if(x<=mid) ans=max(ans,query(ls[p],l,mid,x,y));
if(y>mid) ans=max(ans,query(rs[p],mid+1,r,x,y));
return ans;
}
int merge(int x,int y) {
if(!x||!y) return x+y;
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
tr[x]=max(tr[x],tr[y]);
return x;
}
}
#undef mid
using namespace Segment_Tree;
namespace Tree {
int rt,f[maxn],sz[maxn],size,vis[maxn],data_cnt,c[maxn],ans,ss[maxn];
void get_rt(int x,int fa) {
sz[x]=1,f[x]=1;
for(int i=st[x];i<=ed[x];i++)
if(e[i].to!=fa&&(!vis[e[i].to]))
get_rt(e[i].to,x),sz[x]+=sz[e[i].to],f[x]=max(f[x],sz[e[i].to]);
f[x]=max(f[x],size-sz[x]);
if(f[rt]>f[x]) rt=x;
}
struct data {int dep,dis;}d[maxn];
void get_data(int x,int fa,int dep,int col,int sum) {
if(dep>r) return ;
for(int i=st[x];i<=ed[x];i++) {
if(e[i].to==fa||vis[e[i].to]) continue;
d[++data_cnt]=(data){dep+1,sum+((col==e[i].w)?0:c[e[i].w])};
get_data(e[i].to,x,dep+1,e[i].w,sum+((col==e[i].w)?0:c[e[i].w]));
}
}
void solve(int x) {
vis[x]=1;int r1=0,r2=cnt=0;
for(int i=st[x];i<=ed[x];++i) {
if(e[i].w!=e[i-1].w&&i!=st[x]) r1=merge(r1,r2),r2=0;
if(vis[e[i].to]) continue;
data_cnt=0;
d[++data_cnt]=(data){1,c[e[i].w]};
get_data(e[i].to,x,1,e[i].w,c[e[i].w]);
ss[i]=data_cnt;
for(int j=1;j<=data_cnt;++j) {
if(d[j].dep>r) continue;
if(d[j].dep<r) {
ans=max(ans,d[j].dis+query(r2,1,n,max(1,l-d[j].dep),r-d[j].dep)-c[e[i].w]);
ans=max(ans,d[j].dis+query(r1,1,n,max(1,l-d[j].dep),r-d[j].dep));
}
if(d[j].dep>=l) ans=max(ans,d[j].dis);
}
for(int j=1;j<=data_cnt;++j)
if(d[j].dep<r) modify(r2,1,n,d[j].dep,d[j].dis);
}
for(int i=st[x];i<=ed[x];++i) {
if(vis[e[i].to]) continue;
rt=0,size=ss[i],get_rt(e[i].to,x);
solve(rt);
}
}
}
using namespace Tree;
int main() {
read(n),read(m),read(l),read(r);ans=-inf;
for(int i=1;i<=m;i++) read(c[i]);
for(int i=1,x,y,z;i<n;i++) read(x),read(y),read(z),ins(x,y,z);
sort(e+1,e+n*2-1);int p=1;
for(int i=1;i<=n;i++) {
st[i]=p;while(e[p].fr==i&&p<=n*2-2) p++;ed[i]=p-1;
}
rt=0,f[0]=maxn+1,size=n,get_rt(1,0),solve(rt);write(ans);
return 0;
}
[bzoj4860] [BeiJing2017]树的难题的更多相关文章
- BZOJ4860 Beijing2017树的难题(点分治+单调队列)
考虑点分治.对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化.但是注意到这里每次使用单调队列的复杂度是O(之前的子树最大深度+该子树深度),一不小心就 ...
- BZOJ4860 BJOI2017 树的难题 点分治、线段树合并
传送门 只会线段树……关于单调队列的解法可以去看“重建计划”一题. 看到路径长度$\in [L,R]$考虑点分治.可以知道,在当前分治中心向其他点的路径中,始边(也就是分治中心到对应子树的根的那一条边 ...
- bzoj 4860 [BeiJing2017]树的难题
题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4860 题解 点分治 设当前重心为v 假设已经把所有边按照出发点第一关键字, 颜色第二关键字排 ...
- [BJOI2017]树的难题 点分治 线段树
题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...
- [BJOI2017]树的难题 点分治,线段树合并
[BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...
- BZOJ3257 : 树的难题
设$f[x][i][j]$表示以$x$为根的子树,与$x$连通部分有$i$个黑点,$j$个白点,不联通部分都是均衡的最小代价.若$i>1$,则视作$1$:若$j>2$,则视作$2$. 然后 ...
- 【XSY2307】树的难题
Description Solution 看到这种路径统计问题,一般就想到要用点分治去做. 对于每个重心\(u\),统计经过\(u\)的合法的路径之中的最大值. 第一类路径是从\(u\)出发的,直接逐 ...
- 并不对劲的loj2179:p3714:[BJOI2017]树的难题
题目大意 有一棵树,\(n\)(\(n\leq2*10^5\))个点,每条边\(i\)有颜色\(w_i\),共有\(m\)(\(m\leq n\))种颜色,第\(i\)种颜色的权值是\(c_i\)(\ ...
- [JZOJ3347] 【NOI2013模拟】树的难题
题目 题目大意 给你一棵树,每个节点有三种黑.白.灰三种颜色. 你要割掉一些边(每条边被割需要付出一定的代价),使得森林的每棵树满足: 没有黑点或至多一个白点. 思考历程 这题一看就知道是一个树形DP ...
随机推荐
- I/O流、字符集
1)InputStream.OutPutStream是输出输入的基础流,均为抽象类,提供了read和writer方法,所有的子类均实现read和writer方法,read在遇到输入源的结尾时返回-1. ...
- python计算MD5
python有自带的MD5模块hashlib,用起来简单很多.Python Hashlib模块的使用说明 http://docs.python.org/2/library/hashlib.htmlfd ...
- Laravel-初步使用
一.Laravel环境搭建 1.window环境下环境搭建请参考以下链接: 开发环境搭建 - Windows | <Laravel 开发环境部署> | PHP / Laravel 社区文档 ...
- Hue联合(hdfs yarn hive) 后续......................
1.启动hdfs,yarn start-all.sh 2.启动hive $ bin/hive $ bin/hive --service metastore & $ bin/hive --ser ...
- 数据分析处理库Pandas——常用操作
DataFrame结构排序 备注:group列降序,data列升序. 合并相同项 查找相同项 添加一列,值是其他列的值进行相关操作后的值 删除列 Series结构替换值 一组值按照范围归类 归类后每类 ...
- 工作中使用的linux命令汇总
ln -s /usr/local/tomcat/ ./tomcat 创建软连接到/usr/local/tomcat tar -zxvf apache-kylin-2.4.0-bin-hbase1 ...
- 44- EF + Identity实现
1-配置EF, 需要创建如下几个类 默认User主键为guid类型,现在改成int类型 namespace MvcCookieAuthSample.Models { public class Appl ...
- 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(四):安装MySQL数据库
基于Ubuntu Server 16.04 LTS版本安装和部署Django之(一):安装Python3-pip和Django 基于Ubuntu Server 16.04 LTS版本安装和部署Djan ...
- netty学习记录2
昨天晚上在看到7.2章MessagePack编码器和解码器开发这一章时,书里面没有贴出全部的代码,然后我按照我自己的想法把代码补全后,发现死活没有把代码跑通. 然后花了挺多时间在网上找,很多博客都贴出 ...
- PHP批量替换MySql数据库中的数据内容
<?php //替换数据库内容类 class replace{ public $dbAddress; //数据库地址 public $dbUser; //数据库用户名 public $dbPwd ...