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 ...
随机推荐
- 关于使用Iscroll.js异步加载数据后不能滑动到最底端的问题解决方案
关于使用Iscroll.js异步加载数据后不能滑动到最底端,拉到最下边又弹回去的问题困扰了我老半天,相信很多朋友都遇到了.我刚好不小心解决了,和大家分享一下.由于各种忙,下边就直接上代码吧. (前提是 ...
- WebBench源码分析
源码分析共享地址:https://github.com/fivezh/WebBench 下载源码后编译源程序后即可执行: sudo make clean sudo make & make in ...
- 原来css也可以计算-calc()使用
在浏览其他人的源代码时,看到了一个陌生的属性:width:calc(100% - 10px -10px); 出于好奇心,百度了一下,看到了以下这篇文章,http://www.w3cplus.com/c ...
- 用absolute进行页面的自适应布局
用position:absolute和top,left,bottom,right进行设置可以进行页面的头部,底部,左边框,内容的自适应布局,可以代替position:fixed; <!DOCTY ...
- 远程连接MySQL提示 Host is not allowed to connect to this MySQL server
进入连接的主机修改系统数据库MySQL 下面的user表,把User= root(这里可能是其他你所需要连接的用户名)的这行数据的Host从localhost改为% 如下图: 修改完之后一定要重启My ...
- 钉钉h5项目实战|仿钉钉聊天|h5移动端钉钉案例
最近一直着手开发h5仿钉钉项目,使用到了h5+css3+zepto+wcPop2等技术进行开发,实现了消息.表情.动图发送,仿QQ多人拼合图像,可以选择本地图片,并可以图片.视频预览,仿微信发红包及打 ...
- (转) rabbitmq应用场景
原文:http://blog.csdn.net/wangpengblog/article/details/76405598
- ruby部署之Heroku
下载安装 :https://devcenter.heroku.com/articles/heroku-cli (我是windows,所以我下载windows) cmd黑窗口输入: $ heroku ...
- 原生js动态添加style,添加样式
原生js动态添加style,添加样式 第一种 var style="[assign-url='"+str+"']{display:initial}"; var ...
- 使用httpClient处理get请求或post请求
另外一个版本: http://www.cnblogs.com/wenbronk/p/6671928.html 在java代码中调用http请求, 并将返回的参数进行处理 get请求: public s ...