bzoj 4860 [BeiJing2017]树的难题
题面
https://www.lydsy.com/JudgeOnline/problem.php?id=4860
题解
点分治
设当前重心为v
假设已经把所有边按照出发点第一关键字, 颜色第二关键字排序
对于当前的v 我们顺次考虑他的出边
设当前出边(v,nw) 颜色 col
我们枚举nw的出边
对于一条nw的出边而言, 分为两种情况
1. 颜色与col相同 用线段树维护深度及对应的最值,查询到最大值即可 (v,nw)没有贡献
2. 颜色与col不同 用另一棵线段树维护深度以及与(当前节点的连向其父节点的边的颜色)不同的(连向子节点的边)所对应的子节点对应的子树之内的最值 加上col的权值
向上的时候 将线段树合并
Code
- #include <cstdio>
- #include <cctype>
- #include <algorithm>
- const int maxn=,inf=;
- int ans,n,x,y,z,i,m,l,r,c[maxn*],cnt;
- inline int max(int a,int b){
- return a>b?a:b;
- }
- inline void up(int&a,const int&b){
- if(a<b)a=b;
- }
- inline int getint(){
- char c=getchar();
- int x=,neg=;
- while(!isdigit(c)){
- if(c=='-')neg=-;
- c=getchar();
- }
- while(isdigit(c)){
- x=x*+c-;
- c=getchar();
- }
- return x*neg;
- }
- struct edge{
- int from,to,color;
- }e[maxn<<];
- struct data{
- int dep,sum;
- };
- struct node{
- int v,lc,rc;
- }a[maxn*];
- int merge(int x,int y){
- if(!x || !y )return x|y;
- a[x].lc=merge(a[x].lc,a[y].lc);
- a[x].rc=merge(a[x].rc,a[y].rc);
- up(a[x].v,a[y].v);
- return x;
- }
- void add(int&i,int rl,int rr,int x,int v){
- if(!i)a[i=++cnt]=(node){v,,};
- else up(a[i].v,v);
- if(rl<rr){
- int m=(rl+rr)>>;
- if(x>m)add(a[i].rc,m+,rr,x,v);
- else add(a[i].lc,rl,m,x,v);
- }
- }
- int query(int i,int rl,int rr,int l,int r){
- if(!i)return -inf;
- if(rl==l && rr==r)return a[i].v;
- int m=(rl+rr)>>;
- if(l>m)return query(a[i].rc,m+,rr,l,r);
- else if(r<=m)return query(a[i].lc,rl,m,l,r);
- else return max(query(a[i].lc,rl,m,l,m),query(a[i].rc,m+,rr,m+,r));
- }
- struct tree{
- int xb,h[maxn],n,size[maxn],f[maxn],rt,sum,dep[maxn],ll,ss[maxn];
- bool b[maxn];
- data w[maxn];
- void addedge(int x,int y,int z){
- e[++xb]=(edge){y,x,z};
- e[++xb]=(edge){x,y,z};
- }
- void dfs(int x,int fa){
- size[x]=f[x]=;
- for(int i=h[x];i<h[x+];++i){
- int y=e[i].to;
- if(y!=fa && !b[y]){
- dfs(y,x);
- size[x]+=size[y];
- up(f[x],size[y]);
- }
- }
- up(f[x],sum-size[x]);
- if(f[rt]>f[x])rt=x;
- }
- void got(int x,int fa,int dep,int color,int sum){
- for(int y,i=h[x];i<h[x+];++i){
- y=e[i].to;
- if(y!=fa && !b[y]){
- if(e[i].color==color)w[++ll]=(data){dep+,sum};
- else w[++ll]=(data){dep+,sum+c[e[i].color]};
- got(e[i].to,x,dep+,e[i].color,w[ll].sum);
- }
- }
- }
- void solve(int x){
- b[x]=;
- int i,rt1=,rt2=cnt=,j;
- for(i=h[x];i<h[x+];++i){
- if(i>h[x] && e[i].color>e[i-].color)rt1=merge(rt1,rt2),rt2=;
- if(!b[e[i].to]){
- w[ll=]=(data){,c[e[i].color]};
- got(e[i].to,x,,e[i].color,c[e[i].color]);
- ss[i]=ll;
- for(j=;j<=ll;++j)if(w[j].dep<=r){
- if(w[j].dep>=l)up(ans,w[j].sum);
- if(w[j].dep<r){
- up(ans,query(rt1,,n,max(,l-w[j].dep),r-w[j].dep)+w[j].sum);
- up(ans,query(rt2,,n,max(,l-w[j].dep),r-w[j].dep)-c[e[i].color]+w[j].sum);
- }
- }
- for(j=;j<=ll;++j)if(w[j].dep<=r)add(rt2,,n,w[j].dep,w[j].sum);
- }
- }
- for(i=h[x];i<h[x+];++i)
- if(!b[e[i].to]){
- sum=ss[i];
- rt=;
- dfs(e[i].to,x);
- solve(rt);
- }
- }
- }t;
- bool cmp(const edge&a,const edge&b){
- return a.from==b.from?a.color<b.color:a.from<b.from;
- }
- int main(){
- //freopen("input","r",stdin);
- a[].v=-inf;
- t.n=n=getint();
- m=getint();
- l=getint();
- r=getint();
- for(i=;i<=m;++i)c[i]=getint();
- for(i=;i<n;++i){
- x=getint();
- y=getint();
- z=getint();
- t.addedge(x,y,z);
- }
- std::sort(e+,e+((n-)*)+,cmp);
- for(i=;i<=((n-)<<);++i)
- if(!t.h[e[i].from])t.h[e[i].from]=i;
- t.h[n+]=(n-)<<|;
- t.f[t.rt=]=inf;
- t.sum=n;
- ans=-inf;
- t.dfs(,);
- t.solve(t.rt);
- printf("%d\n",ans);
- }
Review
一开始以为是树形dp 后来发现那是错的
还可以用单调队列过 好像更简单
bzoj 4860 [BeiJing2017]树的难题的更多相关文章
- [bzoj4860] [BeiJing2017]树的难题
Description 给你一棵 n 个点的无根树.树上的每条边具有颜色. 一共有 m 种颜色,编号为 1 到 m.第 i 种颜色的权值为 ci.对于一条树上的简单路径,路径上经过的所有边按顺序组成一 ...
- BZOJ4860 Beijing2017树的难题(点分治+单调队列)
考虑点分治.对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化.但是注意到这里每次使用单调队列的复杂度是O(之前的子树最大深度+该子树深度),一不小心就 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- [BJOI2017]树的难题 点分治 线段树
题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- [BJOI2017]树的难题 点分治,线段树合并
[BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...
- [BZOJ 4771]七彩树(可持久化线段树+树上差分)
[BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...
- BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)
毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...
随机推荐
- Struts2+Spring+Hibernate step by step 04 整合Spring之二,从数据库验证username和password
注:本系列文章部分内容来自王健老师编写ssh整合开发教程 使用Spring的AOP进行项目的事务管理,已经成为非常多企业的首先,Spring做为优秀的开源项目,其在数据库连接.事务管理方面的优势已经显 ...
- dubbo springCloud比较
1.dubbo只是专注于服务之间的治理,配置中心.分布式跟踪等这些内容都需要自己集成 2.dubbo核心功能: a.远程通讯 b.集群容错 c.自动发现 Dubbo SpringCloud 服务注册中 ...
- 编译异常之static和extern---more than one storage class specified
static 和 extern 不能同时共存 http://bbs.bccn.net/thread-58129-1-1.html
- 正则工具类以及FinalClass
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jadyer/article/details/27811103 完整版见https://jadyer. ...
- java反射机制与动态加载类
什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...
- spring、spring MVC、spring Boot
Spring 是一个“引擎” Spring MVC 是基于 Spring 的一个 MVC 框架 Spring Boot 是基于 Spring4 的条件注册的一套快速开发整合包 Spring 最初利用“ ...
- Windows下VMware虚拟机使用Centos,Docker方式安装openstf的小坑
今天使用docker方式安装openstf碰到了一小坑,坑了我半天.特此记录! docker方式安装stf就不说了,网上教程一大把. 但是... 安装完之后.进入web控制界面,手机连接的好好的.但硕 ...
- FZU1901 Period II —— KMP next数组
题目链接:https://vjudge.net/problem/FZU-1901 Problem 1901 Period II Accept: 575 Submit: 1495Time Lim ...
- MYSQL进阶学习笔记七:MySQL触发器的创建,应用及管理!(视频序号:进阶_16,17)
知识点八:MySQL触发器的应用(16,17) 触发器的定义: 什么是触发器: 触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据是触发执行,他比数据库本身标准的功能有更精细和更复杂的数据 ...
- 【转】Java数字抽奖游戏核心代码
1. [代码][Java]代码 package com.luiszhang.test; import java.util.Arrays; /** * NumberLotteryGame * 一个 ...