题面

https://www.lydsy.com/JudgeOnline/problem.php?id=4860

题解

点分治

设当前重心为v

假设已经把所有边按照出发点第一关键字, 颜色第二关键字排序

对于当前的v 我们顺次考虑他的出边

设当前出边(v,nw) 颜色 col

我们枚举nw的出边

对于一条nw的出边而言, 分为两种情况

1. 颜色与col相同   用线段树维护深度及对应的最值,查询到最大值即可 (v,nw)没有贡献

2. 颜色与col不同   用另一棵线段树维护深度以及与(当前节点的连向其父节点的边的颜色)不同的(连向子节点的边)所对应的子节点对应的子树之内的最值 加上col的权值

向上的时候 将线段树合并

Code

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <algorithm>
  4. const int maxn=,inf=;
  5. int ans,n,x,y,z,i,m,l,r,c[maxn*],cnt;
  6. inline int max(int a,int b){
  7. return a>b?a:b;
  8. }
  9. inline void up(int&a,const int&b){
  10. if(a<b)a=b;
  11. }
  12. inline int getint(){
  13. char c=getchar();
  14. int x=,neg=;
  15. while(!isdigit(c)){
  16. if(c=='-')neg=-;
  17. c=getchar();
  18. }
  19. while(isdigit(c)){
  20. x=x*+c-;
  21. c=getchar();
  22. }
  23. return x*neg;
  24. }
  25. struct edge{
  26. int from,to,color;
  27. }e[maxn<<];
  28. struct data{
  29. int dep,sum;
  30. };
  31. struct node{
  32. int v,lc,rc;
  33. }a[maxn*];
  34. int merge(int x,int y){
  35. if(!x || !y )return x|y;
  36. a[x].lc=merge(a[x].lc,a[y].lc);
  37. a[x].rc=merge(a[x].rc,a[y].rc);
  38. up(a[x].v,a[y].v);
  39. return x;
  40. }
  41. void add(int&i,int rl,int rr,int x,int v){
  42. if(!i)a[i=++cnt]=(node){v,,};
  43. else up(a[i].v,v);
  44. if(rl<rr){
  45. int m=(rl+rr)>>;
  46. if(x>m)add(a[i].rc,m+,rr,x,v);
  47. else add(a[i].lc,rl,m,x,v);
  48. }
  49. }
  50. int query(int i,int rl,int rr,int l,int r){
  51. if(!i)return -inf;
  52. if(rl==l && rr==r)return a[i].v;
  53. int m=(rl+rr)>>;
  54. if(l>m)return query(a[i].rc,m+,rr,l,r);
  55. else if(r<=m)return query(a[i].lc,rl,m,l,r);
  56. else return max(query(a[i].lc,rl,m,l,m),query(a[i].rc,m+,rr,m+,r));
  57. }
  58. struct tree{
  59. int xb,h[maxn],n,size[maxn],f[maxn],rt,sum,dep[maxn],ll,ss[maxn];
  60. bool b[maxn];
  61. data w[maxn];
  62. void addedge(int x,int y,int z){
  63. e[++xb]=(edge){y,x,z};
  64. e[++xb]=(edge){x,y,z};
  65. }
  66. void dfs(int x,int fa){
  67. size[x]=f[x]=;
  68. for(int i=h[x];i<h[x+];++i){
  69. int y=e[i].to;
  70. if(y!=fa && !b[y]){
  71. dfs(y,x);
  72. size[x]+=size[y];
  73. up(f[x],size[y]);
  74. }
  75. }
  76. up(f[x],sum-size[x]);
  77. if(f[rt]>f[x])rt=x;
  78. }
  79. void got(int x,int fa,int dep,int color,int sum){
  80. for(int y,i=h[x];i<h[x+];++i){
  81. y=e[i].to;
  82. if(y!=fa && !b[y]){
  83. if(e[i].color==color)w[++ll]=(data){dep+,sum};
  84. else w[++ll]=(data){dep+,sum+c[e[i].color]};
  85. got(e[i].to,x,dep+,e[i].color,w[ll].sum);
  86. }
  87. }
  88. }
  89. void solve(int x){
  90. b[x]=;
  91. int i,rt1=,rt2=cnt=,j;
  92. for(i=h[x];i<h[x+];++i){
  93. if(i>h[x] && e[i].color>e[i-].color)rt1=merge(rt1,rt2),rt2=;
  94. if(!b[e[i].to]){
  95. w[ll=]=(data){,c[e[i].color]};
  96. got(e[i].to,x,,e[i].color,c[e[i].color]);
  97. ss[i]=ll;
  98. for(j=;j<=ll;++j)if(w[j].dep<=r){
  99. if(w[j].dep>=l)up(ans,w[j].sum);
  100. if(w[j].dep<r){
  101. up(ans,query(rt1,,n,max(,l-w[j].dep),r-w[j].dep)+w[j].sum);
  102. up(ans,query(rt2,,n,max(,l-w[j].dep),r-w[j].dep)-c[e[i].color]+w[j].sum);
  103. }
  104. }
  105. for(j=;j<=ll;++j)if(w[j].dep<=r)add(rt2,,n,w[j].dep,w[j].sum);
  106. }
  107. }
  108. for(i=h[x];i<h[x+];++i)
  109. if(!b[e[i].to]){
  110. sum=ss[i];
  111. rt=;
  112. dfs(e[i].to,x);
  113. solve(rt);
  114. }
  115. }
  116. }t;
  117. bool cmp(const edge&a,const edge&b){
  118. return a.from==b.from?a.color<b.color:a.from<b.from;
  119. }
  120. int main(){
  121. //freopen("input","r",stdin);
  122. a[].v=-inf;
  123. t.n=n=getint();
  124. m=getint();
  125. l=getint();
  126. r=getint();
  127. for(i=;i<=m;++i)c[i]=getint();
  128. for(i=;i<n;++i){
  129. x=getint();
  130. y=getint();
  131. z=getint();
  132. t.addedge(x,y,z);
  133. }
  134. std::sort(e+,e+((n-)*)+,cmp);
  135. for(i=;i<=((n-)<<);++i)
  136. if(!t.h[e[i].from])t.h[e[i].from]=i;
  137. t.h[n+]=(n-)<<|;
  138. t.f[t.rt=]=inf;
  139. t.sum=n;
  140. ans=-inf;
  141. t.dfs(,);
  142. t.solve(t.rt);
  143. printf("%d\n",ans);
  144. }

Review

一开始以为是树形dp 后来发现那是错的

还可以用单调队列过 好像更简单

bzoj 4860 [BeiJing2017]树的难题的更多相关文章

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

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

  2. BZOJ4860 Beijing2017树的难题(点分治+单调队列)

    考虑点分治.对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化.但是注意到这里每次使用单调队列的复杂度是O(之前的子树最大深度+该子树深度),一不小心就 ...

  3. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

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

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

  5. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  6. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

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

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

  8. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  9. BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)

    毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...

随机推荐

  1. Struts2+Spring+Hibernate step by step 04 整合Spring之二,从数据库验证username和password

    注:本系列文章部分内容来自王健老师编写ssh整合开发教程 使用Spring的AOP进行项目的事务管理,已经成为非常多企业的首先,Spring做为优秀的开源项目,其在数据库连接.事务管理方面的优势已经显 ...

  2. dubbo springCloud比较

    1.dubbo只是专注于服务之间的治理,配置中心.分布式跟踪等这些内容都需要自己集成 2.dubbo核心功能: a.远程通讯 b.集群容错 c.自动发现 Dubbo SpringCloud 服务注册中 ...

  3. 编译异常之static和extern---more than one storage class specified

    static 和 extern 不能同时共存 http://bbs.bccn.net/thread-58129-1-1.html

  4. 正则工具类以及FinalClass

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jadyer/article/details/27811103 完整版见https://jadyer. ...

  5. java反射机制与动态加载类

    什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...

  6. spring、spring MVC、spring Boot

    Spring 是一个“引擎” Spring MVC 是基于 Spring 的一个 MVC 框架 Spring Boot 是基于 Spring4 的条件注册的一套快速开发整合包 Spring 最初利用“ ...

  7. Windows下VMware虚拟机使用Centos,Docker方式安装openstf的小坑

    今天使用docker方式安装openstf碰到了一小坑,坑了我半天.特此记录! docker方式安装stf就不说了,网上教程一大把. 但是... 安装完之后.进入web控制界面,手机连接的好好的.但硕 ...

  8. FZU1901 Period II —— KMP next数组

    题目链接:https://vjudge.net/problem/FZU-1901  Problem 1901 Period II Accept: 575    Submit: 1495Time Lim ...

  9. MYSQL进阶学习笔记七:MySQL触发器的创建,应用及管理!(视频序号:进阶_16,17)

    知识点八:MySQL触发器的应用(16,17) 触发器的定义: 什么是触发器: 触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据是触发执行,他比数据库本身标准的功能有更精细和更复杂的数据 ...

  10. 【转】Java数字抽奖游戏核心代码

    1. [代码][Java]代码    package com.luiszhang.test; import java.util.Arrays; /** * NumberLotteryGame * 一个 ...