[BJOI2017]树的难题

LG传送门

点分治+线段树合并。

我不会写单调队列,所以就写了好写的线段树。

考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理。用一棵动态开点线段树维护颜色不同的子树的信息,另一棵动态开点线段树维护颜色相同的子树的信息,同时按照题目要求更新答案。当子树颜色变化时,就把第二棵线段树合并到第一棵里面去就好了。

代码实现有点繁琐,我调了很久。。。

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<vector>
#define R register
#define I inline
#define Z first
#define Y second
using namespace std;
const int S=200003,M=6000003,inf=0x3f3f3f3f;
char buf[1000000],*p1,*p2;
I char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,S,stdin),p1==p2)?EOF:*p1++;}
I int rd(){R int f=0,b=1; R char c=gc();while((c<48||c>57)&&c!=45) c=gc();if(c==45) b=0,c=gc();while(c>47&&c<58) f=f*10+(c^48),c=gc();return b?f:~f+1;
}
vector<pair<int,int> > g[S];
struct T{int l,r,f;}a[M];
int c[S],s[S],t[S],h[S],v[S],n,m,e,L,U,u,r,o=-inf,A,B;
I int max(int x,int y){return x>y?x:y;}
I void add(int x,int y,int z){g[x].push_back(make_pair(z,y)),++s[x];}
I void ini(){a[++e].f=-inf,a[e].l=a[e].r=0;}
int mrg(int k,int t){if(!k) return t;if(!t) return k;a[k].f=max(a[k].f,a[t].f),a[k].l=mrg(a[k].l,a[t].l),a[k].r=mrg(a[k].r,a[t].r);return k;
}
void ins(int &k,int l,int r,int x,int v){if(!k) ini(),k=e;if(l==r){a[k].f=max(a[k].f,v); return ;}R int m=l+r>>1;if(x<=m) ins(a[k].l,l,m,x,v);else ins(a[k].r,m+1,r,x,v);a[k].f=max(a[a[k].l].f,a[a[k].r].f);
}
int qry(int k,int l,int r,int x,int y){if(!k) return -inf;if(x<=l&&r<=y) return a[k].f;R int m=l+r>>1,o=-inf;if(x<=m) o=max(o,qry(a[k].l,l,m,x,y));if(m<y) o=max(o,qry(a[k].r,m+1,r,x,y));return o;
}
void gsz(int x,int f){t[x]=1;for(R int i=0,y;i<s[x];++i)if(!v[y=g[x][i].Y]&&y^f)gsz(y,x),t[x]+=t[y];
}
void grt(int x,int f,int a){R int i,y,m=0;for(i=0;i<s[x];++i)if(!v[y=g[x][i].Y]&&y^f)grt(y,x,a),m=max(m,t[y]);m=max(m,a-t[x]);if(m<u) u=m,r=x;
}
void dfs(int x,int f,int r,int l,int d){if(l>U) return ;h[l]=max(h[l],d);for(R int i=0,y,z;i<s[x];++i)if(!v[y=g[x][i].Y]&&y^f)z=g[x][i].Z,dfs(y,x,z,l+1,z^r?d+c[z]:d);
}
void dac(int x){R int i,j,y,z,l;e=A=B=0,u=n,gsz(x,0),grt(x,0,t[x]),gsz(r,0),v[r]=1,l=r;for(i=0;i<s[r];++i)if(!v[y=g[r][i].Y]){z=g[r][i].Z,memset(h,-0x3f,sizeof(int)*(t[y]+1));if(B&&z^g[r][i-1].Z)A=mrg(A,B),B=0;dfs(y,r,z,1,c[z]);for(j=1;j<=t[y]&&j<U&&h[j]^h[0];++j)o=max(max(o,L<=j&&j<=U?h[j]:-inf),max(qry(A,1,U,max(1,L-j),U-j),qry(B,1,U,max(1,L-j),U-j)-c[z])+h[j]);o=max(o,h[U]);for(j=1;j<=t[y]&&j<U&&h[j]^h[0];++j)ins(B,1,U,j,h[j]);}for(i=0;i<s[l];++i)if(!v[y=g[l][i].Y])dac(y);
}
int main(){R int i,x,y,z;n=rd(),m=rd(),L=rd(),U=rd();for(i=1;i<=m;++i)c[i]=rd();for(i=1;i<n;++i)x=rd(),y=rd(),z=rd(),add(x,y,z),add(y,x,z);for(i=1;i<=n;++i)sort(g[i].begin(),g[i].end());memset(h,-0x3f,sizeof h),a[0].f=-inf,dac(1),printf("%d",o);return 0;
}

转载于:https://www.cnblogs.com/cj-chd/p/10116932.html

[BJOI2017]树的难题 点分治,线段树合并相关推荐

  1. 【bzoj4372】烁烁的游戏 动态点分治+线段树

    题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作: Q x:询问x的点权. M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m 接下来的 ...

  2. 洛谷T44252 线索_分治线段树_思维题

    分治线段树,其实就是将标记永久化,到最后再统一下传所有标记. 至于先后顺序,可以给每个节点开一个时间戳. 一般地,分治线段树用于离线,只查询一次答案的题目. 本题中,标记要被下传 222 次. Cod ...

  3. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  4. [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]

    [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...

  5. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围 ...

  6. 2019ICPC上海网络赛A 边分治+线段树

    题目: 给定一棵树, 带边权. 现在有2种操作: 1.修改第i条边的权值. 2.询问u到其他一个任意点的最大距离是多少. 解法:边分治+线段树 首先我们将所有的点修改和边修改都存在对应的边里面. 然后 ...

  7. P6242-[模板]线段树3【吉司机线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6242 题目大意 给出一个长度为nnn的序列aaa,mmm次要求支持操作 区间加上一个值kkk 区间所有aia_i ...

  8. 【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)

    Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改 ...

  9. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

最新文章

  1. (筆記) 如何安裝Altera USB Blaster? (SOC) (Quartus II) (DE2)
  2. linux 判断网线是否插入
  3. CentOS7使用systemctl添加自定义服务
  4. MySQL的索引特性
  5. Springboot06配制拦截器
  6. C#入门详解(12)
  7. excel高级筛选怎么用_excel中使用高级筛选7个示例、多个条件、复制到另一个工作表公式...
  8. 渐变色彩艺术海报背景素材|感官刺激、个性突出
  9. 建造游乐园(play)
  10. DSP课设项目(ICETEK-VC5509-EDU)
  11. pygame 鼠标事件
  12. 电脑主板故障维修案例
  13. 学习统计学,必看的书单推荐
  14. 信号与系统奥本海姆_魏小石 “奥本海姆、电子信息系统与20世纪民间传统音乐”讲座预告...
  15. 国内的虚拟服务器推荐,虚拟空间哪个好(国内比较的几款虚拟主机推荐)
  16. 四、AOSP-开机报错
  17. 陷阱技术探秘 ----动态汉化Windows技术的分析
  18. Linux下查看CPU、内存、磁盘使用情况,并计算其使用率
  19. 信息学奥赛一本通2063
  20. 百度云虚拟主机详细使用流程

热门文章

  1. oppo手机计算机,OPPO手机助手
  2. 生命游戏c语言代码,c++生命游戏源码
  3. java8 stream().map().collect()用法
  4. 怎样改变java编码风格_如何说服同事修改些代码的风格(JAVA的)。。求指引
  5. java编码规范文档 下载_软件项目实训及课程设计指导——制定待开发项目中各种文档的规范...
  6. 《Python入门到精通》函数
  7. [POI2014]Solar Panels
  8. awk分割列 输出时间相关
  9. 单纯形法MATALAB实现
  10. pg_restore使用