BZOJ4381 : [POI2015]Odwiedziny / Luogu3591[POI2015]ODW - 分块+树剖
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 - 分块+树剖的更多相关文章
- HDU5840 Problem This world need more Zhu 分块 树剖
给一颗n个点的有点权的树,有m个询问,对于每个询问u,v,k,首先将点u到点v的最短路径上的所有点按顺序编号,u的编号为1,求树链上所有点的新编号cnt满足cnt%k==0的点的权值的最大值.n,m, ...
- [POI2015]Odwiedziny
[POI2015]Odwiedziny 题目大意: 一棵\(n(n\le5\times10^4)\)个点的树,\(n\)次询问从一个点到另一个点的路径上,每次跳\(k\)个点,所经过的点权和. 思路: ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...
- 【UOJ#435】【集训队作业2018】Simple Tree 分块+树链剖分
题目大意: 有一棵有根树,根为 1 ,点有点权.现在有 m 次操作,操作有 3 种:1 x y w ,将 x 到 y 的路径上的点点权加上 w (其中 w=±1w=±1 ):2 x y ,询问在 x ...
- 【bzoj2141】排队 分块+树状数组
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别, ...
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...
- 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu
https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...
- BZOJ 4765(分块+树状数组)
题面 传送门 "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些 .普通计算机能计算数列区间和,而普通计算姬能计算树中子树和.更 ...
随机推荐
- redis 延时任务 看一篇成高手系列2
引言 在开发中,往往会遇到一些关于延时任务的需求.例如 生成订单30分钟未支付,则自动取消 生成订单60秒后,给用户发短信 对上述的任务,我们给一个专业的名字来形容,那就是延时任务.那么这里就会产生一 ...
- ID的故事
随心所欲.这个时代比较中二吧,刚出国,也买了房,年纪轻轻的觉得自己好像很牛B的样子. 失败悲观的路人甲.大约是13年的时候,突遭重击,一下子悲观失望,死的心都有.为此买了那种自杀也会给赔偿的保险(买后 ...
- Delphi IdHTTP1下载文件防止假死 (
在Form1中添加控件:两个Indy控件:IdAntiFreeze1,IdHTTP1;一个按钮 :Button1;一个进度条 :ProgressBar1 显示下载速度 procedure TForm1 ...
- Python字符串列表元祖字典的公共方法
运算符 运算符 Python 表达式 结果 描述 支持的数据类型 + [1, 2] + [3, 4] [1, 2, 3, 4] 合并 字符串.列表.元组 * 'Hi!' * 4 ['Hi!', 'Hi ...
- 移植Valgrind检测Android JNI内存泄漏
1.相关工具 Valgrind:从Valgrind官网下载最新的源码包,我这里用的是:valgrind 3.14.0 (tar.bz2) [17MB] - 9 October 2018. Ubuntu ...
- python 前后端分离 简单的数据库返回接口
1.使用node http-server 起本地服务器 或者打开nginx 直接用nginx的默认页面也可以 (用下面的html文件替换nginx下html文件夹下的index.html) http ...
- 洛谷P1605走迷宫
传送 这是一道dfs,但是...但是....但是它竟然被放在bfs练习题辣!!!! 打了半天bfs,发现路径不会标记了,于是发现好像有什么不对的,似乎dfs要简单一点,于是半路跑去打dfs,结果打了半 ...
- C# WinForm 实现窗体淡入淡出
有时候我们需要给窗体的打开和关闭添加点动画效果.最近正好有这类需求,于是研究了下窗体的淡入淡出,很简单就实现了,这里发表下成果,以供朋友们使用. 在Windows,有一个API,可以设置窗体的可见度, ...
- 关于CPU CACHE工作机制的学习
转自:http://blog.csdn.net/notbaron/article/details/48143409 1. 存储层次结构 由于两个不谋而合的因素如下: l 硬件:由于不同存储技术的访 ...
- vue-cli 选项无法选问题
winpty vue.cmd create admin 这样创建就可以了