LOJ#6463 AK YOI 树分治+线段树合并
既然是树上路径统计问题,不难想到要使用树分治,这里以点分治为例
由点分治的性质,每层只需要考虑经过重心的路径
因为需要维护路径长度在一定范围内的最大权值和,所以要用一个数据结构维护一下到根节点距离在一定范围内的最大权值和
显然线段树是一个不错的选择,对每个子树建立一个线段树,根节点的答案用每个子树的线段树都更新一遍即可
考虑更新子树中的点的答案,这时需要使用除这棵子树外的所有子树的线段树一起更新
我们可以使用线段树合并来维护,给子树任意确定一个顺序,然后通过维护每个子树的前缀和后缀线段树的并即可快速得到除去某棵子树后的线段树
显然复杂度是有保证的,因为线段树合并的复杂度无论如何都不会高于暴力插入三遍
总复杂度\(O(n\log^2 n)\),常数应该不小,不过跑的挺快233333
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005,maxm=maxn*100;
const long long INF=0x5f5f5f5f5f5f5f5fll;
void solve(int,int);
int getcenter(int,int);
int getdis(int);
void getans(int,int);
void modify(int,int,int&);
int merge(int,int);
long long query(int,int,int);
long long mx[maxm];
int lc[maxm],rc[maxm],cnt=0,root[maxn],prefix[maxn],suffix[maxn];
vector<int>G[maxn];
bool vis[maxn];
long long w[maxn],ans[maxn],ant[maxn],tmp;
int p[maxn],size[maxn],son[maxn],q[maxn],d[maxn],pr[maxn],nx[maxn];
int n,m,L,R,val[maxn],s,t;
int main(){
mx[0]=-INF;
scanf("%d%d%d",&n,&L,&R);
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
ans[i]=-3472328296227680305ll;
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
solve(1,n);
for(int i=1;i<=n;i++){
if(i>1)printf(" ");
printf("%lld",ans[i]);
}
printf("\n");
return 0;
}
void solve(int x,int sz){
x=getcenter(x,sz);
m=sz;
vis[x]=true;
w[x]=val[x];
d[x]=0;
if(sz==1)return;
s=0;
tmp=w[x];
modify(0,m,root[x]);
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]){
p[G[x][i]]=x;
getdis(G[x][i]);
}
s=L;t=R;
for(int i=0,last=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]){
if(s<=m)ans[x]=max(ans[x],query(0,m,root[G[x][i]]));
prefix[G[x][i]]=merge(prefix[last],root[G[x][i]]);
pr[G[x][i]]=last;
last=G[x][i];
}
ant[x]=-INF;
for(int i=(int)G[x].size()-1,last=0;~i;i--)
if(!vis[G[x][i]]){
suffix[G[x][i]]=merge(suffix[last],root[G[x][i]]);
nx[G[x][i]]=last;
last=G[x][i];
}
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]])getans(G[x][i],val[x]);
ans[x]=max(ans[x],ant[x]);
root[x]=0;
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]){
pr[G[x][i]]=nx[G[x][i]]=0;
root[G[x][i]]=prefix[G[x][i]]=suffix[G[x][i]]=0;
}
cnt=0;
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]])solve(G[x][i],size[G[x][i]]);
}
int getcenter(int x,int s){
int head=0,tail=0;
q[tail++]=x;
while(head!=tail){
x=q[head++];
size[x]=1;
son[x]=0;
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]&&G[x][i]!=p[x]){
p[G[x][i]]=x;
q[tail++]=G[x][i];
}
}
for(int i=tail-1;i;i--){
x=q[i];
size[p[x]]+=size[x];
if(size[x]>size[son[p[x]]])son[p[x]]=x;
}
x=q[0];
while(son[x]&&size[son[x]]>(s>>1))x=son[x];
return x;
}
int getdis(int x){
int head=0,tail=0,rt=x;
q[tail++]=x;
while(head!=tail){
x=q[head++];
s=d[x]=d[p[x]]+1;
tmp=w[x]=w[p[x]]+val[x];
modify(0,m,root[rt]);
size[x]=1;
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]&&G[x][i]!=p[x]){
p[G[x][i]]=x;
q[tail++]=G[x][i];
}
}
for(int i=tail-1;i;i--){
x=q[i];
size[p[x]]+=size[x];
}
return d[q[tail-1]];
}
void getans(int x,int v){
int head=0,tail=0,rt=merge(prefix[pr[x]],suffix[nx[x]]);
q[tail++]=x;
while(head!=tail){
x=q[head++];
s=L-d[x];
t=R-d[x];
if(t<0||s>m)ant[x]=-INF;
else ant[x]=w[x]-v+query(0,m,rt);
if(s<=0&&t>=0)ant[x]=max(ant[x],w[x]);
for(int i=0;i<(int)G[x].size();i++)
if(!vis[G[x][i]]&&G[x][i]!=p[x]){
p[G[x][i]]=x;
q[tail++]=G[x][i];
}
}
for(int i=tail-1;~i;i--){
x=q[i];
ant[p[x]]=max(ant[p[x]],ant[x]);
ans[x]=max(ans[x],ant[x]);
}
}
void modify(int l,int r,int &rt){
if(!rt){
rt=++cnt;
mx[rt]=-INF;
lc[rt]=rc[rt]=0;
}
mx[rt]=max(mx[rt],tmp);
if(l==r)return;
int mid=(l+r)>>1;
if(s<=mid)modify(l,mid,lc[rt]);
else modify(mid+1,r,rc[rt]);
}
int merge(int x,int y){
if(!x||!y)return x|y;
int z=++cnt;
mx[z]=max(mx[x],mx[y]);
lc[z]=merge(lc[x],lc[y]);
rc[z]=merge(rc[x],rc[y]);
return z;
}
long long query(int l,int r,int rt){
if(s<=l&&t>=r)return mx[rt];
int mid=(l+r)>>1;
if(t<=mid)return query(l,mid,lc[rt]);
if(s>mid)return query(mid+1,r,rc[rt]);
return max(query(l,mid,lc[rt]),query(mid+1,r,rc[rt]));
}
LOJ#6463 AK YOI 树分治+线段树合并的更多相关文章
- UVALive 7148 LRIP【树分治+线段树】
题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...
- 【BZOJ4372】烁烁的游戏 动态树分治+线段树
[BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...
- LOJ 6145 Easy (动态点分治+线段树)
题目传送门 先建出来点分树,以每个点为根开线段树,维护点分子树内编号为$[l,r]$的儿子到根的距离最小值 每次查询$x$开始,沿着点分树向上跑,在每个点的线段树的$[l,r]$区间里都查一遍取$mi ...
- 【BZOJ3730】震波 动态树分治+线段树
[BZOJ3730]震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土 ...
- 7.18 NOI模拟赛 因懒无名 线段树分治 线段树维护直径
LINK:因懒无名 20分显然有\(n\cdot q\)的暴力. 还有20分 每次只询问一种颜色的直径不过带修改. 容易想到利用线段树维护直径就可以解决了. 当然也可以进行线段树分治 每种颜色存一下直 ...
- bzoj3730 [震波][动态树分治+线段树+LCA]
震波 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 1573 Solved: 358[Submit][Status][Discuss] Descri ...
- LOJ.121.[离线可过]动态图连通性(线段树分治 按秩合并)
题目链接 以时间为下标建线段树.线段树每个节点开个vector. 对每条边在其出现时间内加入线段树,即,把这条边按时间放在线段树的对应区间上,会影响\(O(\log n)\)个节点. 询问就放在线段树 ...
- BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)
题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...
- 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树
题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...
随机推荐
- python实战——网络爬虫
学习网络爬虫的目的: 1,可以私人定制一个搜索引擎,可以深层次的了解搜索引擎的工作原理. 2,大数据时代,要进行数据分析,首先要有数据源,学习爬虫,可以让我们获取更多的数据. 3,从业人员可以可好的利 ...
- 小A老师的学习法
3.13
- 【xsy1120】 支援(assist) dp+卡常
妙啊算错时间复杂度了 题目大意:给你一棵$n$个节点的二叉树,每个节点要么是叶子节点,要么拥有恰好两个儿子. 令$m$为叶子节点个数,你需要在这棵二叉树中选择$i$个叶子节点染色,叶节点染色需要一定的 ...
- 放弃jQuery,使用原生js吧!
转自:http://itakeo.com/blog/2015/07/28/nojq/ 随着IE6.7.8的逐渐淘汰,HTML5的兴起,以及侧重点放在了移动端,jQuery可能变的不在那么重要,原生一样 ...
- cat /proc/sys/net/ipv4/ip_forward 0 解决办法
[root@localhost java]# cat /proc/sys/net/ipv4/ip_forward 出于安全考虑,Linux系统默认是禁止数据包转发的. 所谓转发即当主机拥有多于一块的网 ...
- 【链表】Remove Duplicates from Sorted List II(三指针)
题目: Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct ...
- CentOS6.5下Ambari安装搭建部署大数据集群(图文分五大步详解)(博主强烈推荐)
第一步: Ambari安装之Ambari安装前准备(CentOS6.5)(一) 第二步: Ambari安装之部署本地库(镜像服务器)(二) 第三步: Ambari安装之安装并配置Ambari-serv ...
- java 实现 HTTP请求(GET、POST)的方法
使用Java进行服务调用时,避免不了要使用模拟HTTP请求来实现模拟,我在开发过程中恰巧遇到了这类的业务需求,所以就对这类的方法进行了一次总结,原理层次的东西暂时不考虑,毕竟HTTP的底层实现啥的,东 ...
- java面试②基础部分
2.1.3 讲一下java中int数据占几个字节 java中有几种基本数据类型? 2.1.4. 面向对象的特征有哪些方面 有四大基本特征:封装.抽象.继承.多态 1)封装,即将对象封装成一个高度自治和 ...
- Spring4 MVC ContentNegotiatingViewResolver多种输出格式实
前段时间在一个项目里面发现,针对Excel的处理没有一个公用的视图,来个下载的需求就要自己去写一堆POI的东西,终于有一天给我也来了几个,还是按照以前的方式来写,写多了真心想吐,后面想想还是有必要整个 ...