题目描述

给定一棵n个点的树,树上每条边的长度都为1,第i个点的权值为a[i]。
Byteasar想要走遍这整棵树,他会按照某个1到n的全排列b走n-1次,第i次他会从b[i]点走到b[i+1]点,并且这一次的步伐大小为c[i]。
对于一次行走,假设起点为x,终点为y,步伐为k,那么Byteasar会从x开始,每步往前走k步,如果最后不足k步就能到达y,那么他会一步走到y。
请帮助Byteasar统计出每一次行走时经过的所有点的权值和。

输入

第一行包含一个正整数n(2<=n<=50000)。表示节点的个数。
第二行包含n个正整数,其中第i个数为a[i](1<=a[i]<=10000),分别表示每个点的权值。
接下来n-1行,每行包含两个正整数u,v(1<=u,v<=n),表示u与v之间有一条边。
接下来一行包含n个互不相同的正整数,其中第i个数为b[i](1<=b[i]<=n),表示行走路线。
接下来一行包含n-1个正整数,其中第i个数为c[i](1<=c[i]<n),表示每次行走的步伐大小。

输出

包含n-1行,每行一个正整数,依次输出每次行走时经过的所有点的权值和

样例输入

5
1 2 3 4 5
1 2
2 3
3 4
3 5
4 1 5 2 3
1 3 1 1

样例输出

10
6
10
5
    
  因为k的大小不确定,所以分情况来做。设p=sqrt(n),当k<=p时,可以预处理出f[i][j]表示i节点以j步伐一直往上走,直到走到根节点(i节点的深度如果不是k的倍数,根节点不计入)为止能得到的点权和,查询时直接求就好了.当k>p时,就要暴力往上走了,可以用重链剖分来实现,单次查询时间复杂度是O(logn+√n),但有一种时间复杂度更优的做法——长链剖分,因为长链剖分可以O(1)查询一个点的k级祖先,因此最多爬√n次,单次查询时间复杂度O(√n)。如何实现参见->长链剖分

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n;
int x,y;
int tot;
int mask;
int b[50010];
int a[50010];
int k[50010];
int d[50010];
int st[50010];
int mx[50010];
int to[100010];
int son[50010];
int top[50010];
int head[50010];
int next[100010];
int f[50010][17];
int up[50010][300];
vector<int>s[50010];
vector<int>t[50010];
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs(int x)
{
d[x]=d[f[x][0]]+1;
mx[x]=d[x];
for(int i=1;i<=16;i++)
{
if(f[x][i-1])
{
f[x][i]=f[f[x][i-1]][i-1];
}
else
{
break;
}
}
int fx=x;
for(int i=1;i<=mask;i++)
{
fx=f[fx][0];
up[x][i]=a[x]+up[fx][i];
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x][0])
{
f[to[i]][0]=x;
dfs(to[i]);
mx[x]=max(mx[x],mx[to[i]]);
if(mx[to[i]]>mx[son[x]])
{
son[x]=to[i];
}
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
if(son[x])
{
dfs2(son[x],tp);
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x][0]&&to[i]!=son[x])
{
dfs2(to[i],to[i]);
}
}
}
void find(int x)
{
int rt=x;
int len=mx[x]-d[x];
x=f[rt][0];
while(d[rt]-d[x]<=len&&x)
{
s[rt].push_back(x);
x=f[x][0];
}
x=rt;
while(son[x])
{
t[rt].push_back(son[x]);
x=son[x];
}
}
int find_ancestor(int x,int k)
{
if(k==0)
{
return x;
}
if(d[x]<=k)
{
return 0;
}
x=f[x][st[k]];
k-=(1<<st[k]);
if(k==0)
{
return x;
}
if(k==d[x]-d[top[x]])
{
return top[x];
}
if(k<d[x]-d[top[x]])
{
return t[top[x]][d[x]-d[top[x]]-k-1];
}
return s[top[x]][k-d[x]+d[top[x]]-1];
}
int lca(int x,int y)
{
if(d[x]<d[y])
{
swap(x,y);
}
int dep=d[x]-d[y];
for(int i=0;i<=16;i++)
{
if((dep&(1<<i))!=0)
{
x=f[x][i];
}
}
if(x==y)
{
return x;
}
for(int i=16;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int query(int x,int y,int step)
{
int res=0;
int anc=lca(x,y);
int lx=d[x]-d[anc];
int ly=d[y]-d[anc];
if(step>mask)
{
res+=a[x]+a[y];
while(lx>step)
{
x=find_ancestor(x,step);
res+=a[x];
lx-=step;
}
if(lx+ly-1>=step)
{
y=find_ancestor(y,lx+ly-(lx+ly-1)/step*step);
res+=a[y];
ly=(lx+ly-1)/step*step-lx;
while(ly>step)
{
y=find_ancestor(y,step);
res+=a[y];
ly-=step;
}
}
if(x!=anc&&y!=anc&&(lx==step||ly==step))
{
res+=a[anc];
}
}
else
{
if(lx+ly<=step)
{
res=a[x]+a[y];
}
else
{
res+=a[y];
y=find_ancestor(y,lx+ly-(lx+ly-1)/step*step);
ly=(lx+ly-1)/step*step-lx;
res+=up[x][step]-up[find_ancestor(x,(lx/step)*step+step)][step];
if(ly>=0)
{
res+=up[y][step]-up[find_ancestor(y,(ly/step)*step+step)][step];
}
if(lx%step==0)
{
res-=a[anc];
}
}
}
return res;
}
int main()
{
scanf("%d",&n);
mask=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1);
dfs2(1,1);
for(int i=1;i<=n;i++)
{
if(i==top[i])
{
find(i);
}
}
st[1]=0;
for(int i=2;i<=n;i++)
{
st[i]=st[i>>1]+1;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
}
for(int i=1;i<n;i++)
{
scanf("%d",&k[i]);
}
for(int i=1;i<n;i++)
{
printf("%d\n",query(b[i],b[i+1],k[i]));
}
}

BZOJ4381[POI2015]Odwiedziny——分块+长链剖分的更多相关文章

  1. 【UOJ#33】【UR #2】树上GCD(长链剖分,分块)

    [UOJ#33][UR #2]树上GCD(长链剖分,分块) 题面 UOJ 题解 首先不求恰好,改为求\(i\)的倍数的个数,最后容斥一下就可以解决了. 那么我们考虑枚举一个\(LCA\)位置,在其两棵 ...

  2. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  3. LOJ3053 十二省联考2019 希望 容斥、树形DP、长链剖分

    传送门 官方题解其实讲的挺清楚了,就是锅有点多-- 一些有启发性的部分分 L=N 一个经典(反正我是不会)的容斥:最后的答案=对于每个点能够以它作为集合点的方案数-对于每条边能够以其两个端点作为集合点 ...

  4. BZOJ 3653: 谈笑风生(离线, 长链剖分, 后缀和)

    题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为 ...

  5. 2019.03.11 COGS2652 秘术(天文密葬法)(分数规划+长链剖分)

    传送门 题意:nnn个点的树,每个点两个值a,ba,ba,b,问长度为mmm的路径∑ai∑bi\frac{\sum a_i}{\sum b_i}∑bi​∑ai​​的最大值. 思路:一眼要01分数规划, ...

  6. 【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并

    题目大意 ​ 给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\) ​ \(1\leq n\leq 1 ...

  7. 【Vijos】lxhgww的奇思妙想(长链剖分)

    题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...

  8. 【BZOJ4543】Hotel加强版(长链剖分)

    [BZOJ4543]Hotel加强版(长链剖分) 题面 BZOJ,没有题面 洛谷,只是普通版本 题解 原来我们的\(O(n^2)\)做法是设\(f[i][j]\)表示以\(i\)为根的子树中,距离\( ...

  9. 【BZOJ3653】谈笑风生(长链剖分)

    [BZOJ3653]谈笑风生(长链剖分) 题面 BZOJ 洛谷 权限题啊.... 题解 首先根据题目给的条件,发现\(a,b\)都要是\(c\)的父亲. 所以这三个点是树上的一条深度单增的链. 因为\ ...

随机推荐

  1. Django Web开发基础环境配置流程

    创建虚拟环境 mkvirtualenv django_py3_1.11 -p python3 注意需要联网 安装Django 使用django 1.11.11版本,注意需要联网 pip install ...

  2. Java 集合Collection与List的详解

    1.什么是集合 存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,存储对象,集合是存储对象最常用的一种方式. 集合的出现就是为了持有对象.集合中可以存储任意类型的 ...

  3. 牛客网练习赛t2(线段树)

    题解: 好像因为他说了 数据范围全部在ll以内 所以直接暴力就可以过了 比较正常是用线段树来维护 洛谷上有道模板题是支持加,乘,区间和 而这题还多了区间平方和的操作 按照那题的操作 我们维护的时候保证 ...

  4. 【loj6029】「雅礼集训 2017 Day1」市场&&【uoj#228】基础数据结构练习题

    题解: 这两道题加上区间取min max应该算线段树几道比较不寻常的题目 其实也是挺好理解的 对于区间/d 显然在log次后就会等于0 而我们注意到如果区间中数都相等那么就可以一起除 也就是说每个区间 ...

  5. appstore跳转

    二维码跳转 https://itunes.apple.com/cn/app/id123123123 应用内跳转 this.alertCtrl.create({ title: '更新', message ...

  6. ionic2+集成第三方sdk时,合并多个清单文件的方法

    具体方案android studio官网上已经给出,但需要架梯子,所以这篇文章直接把它搬到墙内,方便查看: 合并多个清单文件 合并优先级 合并冲突启发式算法 合并规则标记 节点标记 属性标记 标记选择 ...

  7. Flink运行在yarn上

    在一个企业中,为了最大化的利用集群资源,一般都会在一个集群中同时运行多种类型的 Workload.因此 Flink 也支持在 Yarn 上面运行: flink on yarn的前提是:hdfs.yar ...

  8. Consumer is not subscribed to any topics or assigned any partitions

    版本: scala:2.11.8 spark:2.11 hbase:1.2.0-cdh5.14.0 报错信息: java.lang.IllegalStateException: Consumer is ...

  9. 关于mac的一些常用操作记录

    之前记录过一个关于mac远程连接window机,实现共享文件的记录,今天记录一些常用的操作,会持续更新. 1.谷歌浏览器 f12的操作 command+option+i 打开调试面板 2.打开指定位置 ...

  10. jenkins使用教程之系统设置

    如果jenkins环境还没有搭建好的话可以看这篇文章点击查看 进入jenkins首页,点击系统管理 点击系统设置,进入系统设置界面 1.主目录,点击高级 主目录是存放Jenkins所有的文件的,工作空 ...