Solution

在步伐$pace$比较小的时候, 我们发现用前缀和直接维护会很快

而在$pace$比较大的时候, 则暴力往上跳会最优

设$blo= \sqrt{N}$

若$pace<=blo$, 则利用前缀和更新,

预处理复杂度$O(N \sqrt{N})$, 查询复杂度$O(1)$

若$pace>blo$,则利用树剖逐渐往上跳

总共要跳$N/pace$次, 一共有$logN$条轻重链, 复杂度为$O(logN+ \sqrt{N})$

代码实现比较麻烦, 我常数写的还很差, 水平低啊QAQ

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define rd read()
#define N 50005
#define M 240
#define R register
using namespace std; int n, blo, a[N], b[N], f[N][M], sum[N][M];
int fa[N], dep[N], top[N], sz[N], son[N], id[N], idf[N], cnt;
int head[N], tot; struct edge {
int nxt, to;
}e[N << ]; inline char nc(){
static char buf[], *p1=buf, *p2=buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, , , stdin), p1 == p2) ? EOF : *p1++;
}
inline int read(){
char ch = nc();int sum = ;
while(!(ch >= '' && ch <= '')) ch = nc();
while(ch >= '' && ch <= '') sum = sum * + ch - , ch = nc();
return sum;
} inline void add(int u, int v) {
e[++tot].to = v;
e[tot].nxt = head[u];
head[u] = tot;
} inline void sw(int &A, int &B) {
A ^= B; B ^= A; A ^= B;
} inline void dfs1(R int u) {
sz[u] = ;
for (R int i = head[u]; i; i = e[i].nxt) {
R int nt = e[i].to;
if (nt == fa[u]) continue;
f[nt][] = fa[nt] = u;
dep[nt] = dep[u] + ;
dfs1(nt);
sz[u] += sz[nt];
if (sz[nt] > sz[son[u]])
son[u] = nt;
}
} inline void dfs2(R int u) {
idf[id[u] = ++cnt] = u;
if (!son[u]) return;
top[son[u]] = top[u];
dfs2(son[u]);
for (R int i = head[u]; i; i = e[i].nxt) {
R int nt = e[i].to;
if (nt == fa[u] || nt == son[u]) continue;
top[nt] = nt;
dfs2(nt);
}
} inline int LCA(R int x, R int y) {
for (;top[x] != top[y]; ) {
if (dep[top[x]] < dep[top[y]]) sw(x, y);
x = fa[top[x]];
}
if (dep[x] < dep[y]) sw(x, y);
return y;
} inline int work1(R int x, R int y, R int pace) {
R int lca = LCA(x, y), len = dep[x] + dep[y] - * dep[lca], res = ;
if (len % pace) {
res += a[y];
y = f[y][len % pace];
len -= len % pace;
}
len = dep[x] - dep[lca];
if (len % pace == ) {
res += sum[x][pace] - sum[lca][pace];
res += sum[y][pace] - sum[lca][pace];
res += a[lca];
return res;
}
R int tmp = f[lca][pace - len % pace];
res += sum[x][pace] - sum[tmp][pace];
if (dep[y] < dep[lca]) return res;
len = dep[y] - dep[lca];
tmp = f[lca][pace - len % pace];
res += sum[y][pace] - sum[tmp][pace];
return res;
} inline int up(R int x, R int d) {
R int y = top[x];
for (; x && dep[x] - dep[y] < d;) {
d -= dep[x] - dep[y] + ;
x = fa[top[x]];
y = top[x];
}
if (!x) return ;
return idf[id[x] - d];
} inline int work2(R int x, R int y, R int pace) {
R int lca = LCA(x, y), len = dep[x] + dep[y] - * dep[lca], res = ;
if (len % pace) {
res += a[y];
y = up(y, len % pace);
len -= len % pace;
}
len = dep[x] - dep[lca];
if (len % pace == ) {
while (x && dep[x] > dep[lca])
res += a[x], x = up(x, pace);
while (y && dep[y] > dep[lca])
res += a[y], y = up(y, pace);
res += a[lca];
return res;
}
while (x && dep[x] > dep[lca])
res += a[x], x = up(x, pace);
while (y && dep[y] > dep[lca])
res += a[y], y = up(y, pace);
return res;
} int main()
{
n = rd; blo = sqrt(n);
for (R int i = ; i <= n; ++i)
a[i] = rd;
for (R int i = ; i < n; ++i) {
int u = rd, v = rd;
add(u, v); add(v, u);
}
dep[] = ; dfs1();
top[] = ; dfs2();
for (R int j = ; j <= blo; ++j)
for (R int i = ; i <= n; ++i)
f[i][j] = f[f[i][j - ]][];
for (R int j = ; j <= blo; ++j)
for (R int i = ; i <= n; ++i)
sum[i][j] = a[i];
for (R int j = ; j <= blo; ++j)
for (R int i = ; i <= n; ++i) {
int x = idf[i];
sum[x][j] += sum[f[x][j]][j];
}
for (R int i = ; i <= n; ++i) b[i] = rd;
for (R int i = ; i < n; ++i) {
R int x = rd;
if (x <= blo) printf("%d\n", work1(b[i], b[i + ], x));
else printf("%d\n", work2(b[i], b[i + ], x));
}
}

BZOJ4381 : [POI2015]Odwiedziny / Luogu3591[POI2015]ODW - 分块+树剖的更多相关文章

  1. HDU5840 Problem This world need more Zhu 分块 树剖

    给一颗n个点的有点权的树,有m个询问,对于每个询问u,v,k,首先将点u到点v的最短路径上的所有点按顺序编号,u的编号为1,求树链上所有点的新编号cnt满足cnt%k==0的点的权值的最大值.n,m, ...

  2. [POI2015]Odwiedziny

    [POI2015]Odwiedziny 题目大意: 一棵\(n(n\le5\times10^4)\)个点的树,\(n\)次询问从一个点到另一个点的路径上,每次跳\(k\)个点,所经过的点权和. 思路: ...

  3. 【BZOJ 3295】动态逆序对 - 分块+树状数组

    题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...

  4. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

  5. 【UOJ#435】【集训队作业2018】Simple Tree 分块+树链剖分

    题目大意: 有一棵有根树,根为 1 ,点有点权.现在有 m 次操作,操作有 3 种:1 x y w ,将 x 到 y 的路径上的点点权加上 w (其中 w=±1w=±1 ):2 x y ,询问在 x ...

  6. 【bzoj2141】排队 分块+树状数组

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别, ...

  7. 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

    题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...

  8. 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu

    https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...

  9. BZOJ 4765(分块+树状数组)

    题面 传送门 "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些 .普通计算机能计算数列区间和,而普通计算姬能计算树中子树和.更 ...

随机推荐

  1. python 基本语句

    python 基本语句 在使用python的变量前必须给它赋值,因为python变量没有默认值. 获取用户输入值 此时需要注意:input函数的返回值为文本或字符串. 一些简单的函数 乘方 绝对值 将 ...

  2. 涨姿势:Java 分业务、分级别实现自定义日志打印

    自定义日志级别 通常的日志框架都有以下几个级别,从低到高TRACE,DEBUG,INFO,WARN,ERROR,FATAL. 默认情况,假如我们定义日志打印级别INFO,它会把大于等于INFO级别的日 ...

  3. React.js 学习总结

    1.用React的优越性 独立,小巧,快速 ReactDOM 会构建一个虚拟的DOM tree, 只有DOM tree 的某个部分发生变化,便重新渲染某个部分. React 判断DOM 是否重新渲染的 ...

  4. numpy学习笔记(三)

    (1)numpy的位操作 序号         操作及描述 1.      bitwise_and 对数组元素执行位与操作 2.      bitwise_or 对数组元素执行位或操作 3.      ...

  5. 某大型跨境电商JVM调优总结

    前提:某大型跨境电商业务发展非常快,线上机器扩容也很频繁,但是对于线上机器的运行情况,特别是jvm内存的情况,一直没有一个统一的标准来给到各个应用服务的owner.经过618大促之后,和运维的同学讨论 ...

  6. win10家庭版 监听无法启动 报TNS-12560 TNS-00530

    首先win10权限问题, 搜索设置->更新和安全 ->恢复->高级启动立即重启 疑难解答-高级选项-启动设置-重启-选择“4” 按“WIN+R”组合键,输入“control user ...

  7. shell:实现linux服务器资源监控并发送告警邮件

    1.安装方式 wget http://10.8.225.126/wsmonitor/install.sh;sh install.sh test@test.com 2.install.sh #!/bin ...

  8. 网页编程工具:EditPlus

    字体:Consolas EditPlus,很土很简单很强大的网页编程工具 http://www.editplus.com/download.html  下载 http://www.cnblogs.co ...

  9. scp: command not found

    scp 不能用? [root@doc]# scp jdk-8u144-linux-x64.tar.gz root@10.10.10.17:/root/ root@10.10.10.17's passw ...

  10. Linux实操篇 vi和vim编辑器

    vi和vim的基本介绍 所有的Linux系统都会内建vi文本编辑器. vim具有程序编辑的能力,可以看做是vi的增强版本,可以主动的以字体颜色辨别语法的正确性,方便程序设计.代码补完.编译及错误跳转等 ...