考虑点分治。对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化。但是注意到这里每次使用单调队列的复杂度是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<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),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][2],Q[N],t,ans=-inf;
bool flag[N];
struct data{int to,nxt,color;
}edge[N<<1];
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]=1;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]+1;make(edge[i].to,k);size[k]+=size[edge[i].to];}
}
int findroot(int k,int s)
{int mx=0;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]<<1)>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=0,tail=1;q[1][0]=k,q[1][1]=last;int h=1,t=0;for (int i=min(d,r);i>=l;i--) ins(i,h,t,g);do{int x=q[++head][0];if (deep[x]>=l&&deep[x]<=r) ans=max(ans,len[x]);if (deep[x]>deep[q[head-1][0]]){pop(r-deep[x],h,t);if (l-deep[x]>=0&&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][1]) len[edge[i].to]+=a[edge[i].color];q[++tail][0]=edge[i].to,q[tail][1]=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]=1;deep[k]=0;make(k,k);int cnt=0;for (int i=p[k];i;i=edge[i].nxt)if (!flag[edge[i].to]){colordeep[edge[i].color]=mxdeep[edge[i].to]=0,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+1,v+cnt+1);for (int i=1;i<=cnt;i++){int t=i-1,d=0;while (t<cnt&&v[t+1].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=1,T=0;for (int j=min(colordeep[v[i-1].y],r);j>=l;j--) ins(j,H,T,f);for (int j=1;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=0;j<=d;j++) f[j]=max(f[j],g[j]),g[j]=-inf;i=t;}for (int i=0;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_JUDGEfreopen("bzoj4860.in","r",stdin);freopen("bzoj4860.out","w",stdout);const char LL[]="%I64d\n";
#elseconst char LL[]="%lld\n";
#endifn=read(),m=read(),l=read(),r=read();for (int i=0;i<=n;i++) f[i]=g[i]=-inf;for (int i=1;i<=m;i++) a[i]=read();for (int i=1;i<n;i++){int x=read(),y=read(),z=read();addedge(x,y,z),addedge(y,x,z);}solve(1);cout<<ans;return 0;
}

转载于:https://www.cnblogs.com/Gloid/p/10004006.html

BZOJ4860 Beijing2017树的难题(点分治+单调队列)相关推荐

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

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

  2. 【BZOJ1758】重建计划,点分治+单调队列

    Time:2016.08.21 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: UPD 2017.1.18 之前的思路删掉了,因为写的太烂,纯属放屁 刚刚知道新加了一组数据,所以原先 ...

  3. 牛客练习赛79E-小G的数学难题【dp,单调队列】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/11169/E 题目大意 给出nnn个三元组(ai,bi,ci)(a_i,b_i,c_i)(ai​,bi​,ci ...

  4. 【HDU6701】Make Rounddog Happy【权值线段树+双向单调队列】

    题意:给你一个序列,求满足要求的子序列个数,其中要求为: 1.子序列的max-子序列长度len<=k 2.子序列中不出现重复的数字 题解:首先看到子序列max,很容易想到枚举最大值然后分治,这个 ...

  5. 入门经典_Chap08_题解总结:极角扫描法 滑动窗口 单调队列 单调栈

    总结  本章主要关注一个重要的问题 – 单调队列和单调栈的使用  同时还有一些其他的问题,如扫描法,递归的思想, 构造, 分治, 二分等 知识点 单调队列 和 单调栈 题目 UVA - 1606 Am ...

  6. P3714 [BJOI2017]树的难题(点分治/线段树/单调队列)

    P3714 [BJOI2017]树的难题 求解树上长度在L到R的树链中颜色段权值和最大的链. 首先求解树上链的问题,而且限制了链的长度,那么我们需要点分治处理,然后考虑每次分治,我们可以把链分成两类, ...

  7. 【BJOI2017】树的难题【点分治】【线段树】

    传送门 传送门 题意:给一棵树,树上有颜色,每种颜色有权值,定义一条路径的权值为所有颜色相同段的权值之和,求长度在[L,R][L,R][L,R]中的路径的最大权值. 数据范围:暴力过不了 显然是个点分 ...

  8. 并不对劲的loj2179:p3714:[BJOI2017]树的难题

    题目大意 有一棵树,\(n\)(\(n\leq2*10^5\))个点,每条边\(i\)有颜色\(w_i\),共有\(m\)(\(m\leq n\))种颜色,第\(i\)种颜色的权值是\(c_i\)(\ ...

  9. [luogu 4292][bzoj 1758][WC2010] 重建计划(点分治 + dp + 单调队列优化 + 启发式合并)

    [WC2010]重建计划 problem solution code problem 洛谷指路 solution 一看那个道路平均价值的式子:AvgValue=∑e∈Sv(e)∣S∣\text{Avg ...

最新文章

  1. Windows系统下的各类用户角色
  2. 稳扎稳打Silverlight(17) - 2.0数据之详解DataGrid, 绑定数据到ListBox
  3. java取number长度_Java中常用方法(NumberMath)
  4. Java实现串口通信的小样例
  5. Spring AOP介绍
  6. python 函数调用列表_python – 根据列表中的字符串调用函数
  7. PYTHON1.day07
  8. 三维点云学习(5)5-实现Deeplearning-PointNet-2-classfication
  9. 像中文的罗马音字体复制_罗马音字体大全可复制
  10. 北大青鸟网络工程师benet培训招生问答
  11. AHU计科(伪)新生指南
  12. 第一次登陆阿里云ECS云服务器及其配置
  13. Gimp 将图片中的颜色更改
  14. 华大(小华)HC32L130工程创建
  15. fpu测试_正点原子STM32F4/F7水星开发板资料连载第五十章 FPU 测试实验
  16. OSChina 周一乱弹 —— 温柔的人应该这样
  17. gateway资源详解
  18. Blinker点灯科技绑定GitHub增加设备数量到10个
  19. 推荐几个值得学习的jQuery文档
  20. 【Appium踩坑】Cannot start the ‘com.xx.xx‘ application. Visit https://github.com/appium/appium/blob/mast

热门文章

  1. InstallShield Premier版本和Professional版本的功能差异
  2. logs is not in the form of topic-partition or topic-partition.uniqueId-delete
  3. gensim出现segmentation Fault解决方案
  4. OpenCV学习笔记六-提高对比度
  5. xampp php连接mysql数据库_关于PHP xampp连接数据库之后查询失败,数据库连接成功,表中也有数据...
  6. mysql如何获取句柄_关于获取进程句柄的问题
  7. WIN10 软连接释放c盘空间
  8. 深度学习(二十一)——SRCNN, DRCN, VDSR
  9. mysql数据库实战_主题:MySQL数据库操作实战
  10. jsp调用controller方法_SpringMVC五大核心组件及调用过程