[POI2015]Odwiedziny

题目大意:

一棵\(n(n\le5\times10^4)\)个点的树,\(n\)次询问从一个点到另一个点的路径上,每次跳\(k\)个点,所经过的点权和。

思路:

分块思想。

当\(k\ge\sqrt n\)时,显然每次询问不会跳超过\(\sqrt n\)次,可以借助树链剖分在\(\mathcal O(\sqrt n)\)的时间内暴力完成询问。

当\(k<\sqrt n\)时,预处理从一个点出发,每次跳\(k\)格,跳到根结点的权值和。可以\(\mathcal O(\log n)\)求LCA,\(\mathcal O(1)\)回答。

时间复杂度\(\mathcal O(n\sqrt n)\)。

源代码:

#include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=50001,B=223;
int n,block,a[N],b[N],c[N];
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int anc[N][B],sum[N][B],dep[N],top[N],son[N],size[N],dfn[N],id[N];
void dfs(const int &x,const int &par) {
size[x]=1;
anc[x][1]=par;
sum[x][1]=sum[par][1]+a[x];
dep[x]=dep[par]+1;
for(register int i=2;i<block;i++) {
anc[x][i]=anc[anc[x][i-1]][1];
sum[x][i]=sum[anc[x][i]][i]+a[x];
}
for(unsigned i=0;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]]) {
son[x]=y;
}
}
}
void dfs(const int &x) {
dfn[x]=++dfn[0];
id[dfn[x]]=x;
top[x]=x==son[anc[x][1]]?top[anc[x][1]]:x;
if(son[x]) dfs(son[x]);
for(unsigned i=0;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==anc[x][1]||y==son[x]) continue;
dfs(y);
}
}
inline int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
x=anc[top[x]][1];
}
if(dep[x]<dep[y]) std::swap(x,y);
return y;
}
inline int father(int x,int k) {
if(k>=dep[x]) return 0;
while(k>=dep[x]-dep[top[x]]+1) {
k-=dep[x]-dep[top[x]]+1;
x=anc[top[x]][1];
}
return id[dfn[x]-k];
}
inline int calc(int x,int y,const int &k) {
if(dep[x]<=dep[y]) return 0;
int ret=0;
if(k<block) {
while(y&&(dep[x]-dep[y])%k) y=anc[y][1];
ret=sum[x][k]-sum[y][k];
} else {
while(dep[x]>dep[y]) {
ret+=a[x];
x=father(x,k);
}
}
return ret;
}
inline int query(int x,int y,const int &k) {
const int z=lca(x,y),dis=dep[x]+dep[y]-dep[z]*2;
int ret=calc(x,z,k);
if(dis%k) {
ret+=a[y];
y=father(y,dis%k);
}
ret+=calc(y,anc[z][1],k);
return ret;
}
int main() {
block=sqrt(n=getint());
for(register int i=1;i<=n;i++) a[i]=getint();
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
dfs(1,0);
dfs(1);
for(register int i=1;i<=n;i++) b[i]=getint();
for(register int i=1;i<n;i++) {
printf("%d\n",query(b[i],b[i+1],getint()));
}
return 0;
}

[POI2015]Odwiedziny的更多相关文章

  1. bzoj4381: [POI2015]Odwiedziny

    这题搞了我一下午……因为一些傻X的问题…… 对于步长大于sqrt(n)的询问,我们可以直接暴力求解 然后,我们可以事先预处理出d[u][step]表示u往上跳,每次跳step步,直到跳到不能跳为止,所 ...

  2. BZOJ4381[POI2015]Odwiedziny——分块+长链剖分

    题目描述 给定一棵n个点的树,树上每条边的长度都为1,第i个点的权值为a[i].Byteasar想要走遍这整棵树,他会按照某个1到n的全排列b走n-1次,第i次他会从b[i]点走到b[i+1]点,并且 ...

  3. BZOJ4381 : [POI2015]Odwiedziny / Luogu3591[POI2015]ODW - 分块+树剖

    Solution 在步伐$pace$比较小的时候, 我们发现用前缀和直接维护会很快 而在$pace$比较大的时候, 则暴力往上跳会最优 设$blo= \sqrt{N}$ 若$pace<=blo$ ...

  4. @bzoj - 4381@ [POI2015] Odwiedziny

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵 n 个点的树,树上每条边的长度都为 1 ,第 i 个点 ...

  5. [Poi2015]

    [POI2015]Łasuchy 一看以为是sb题 简单来说就是每个人获得热量要尽量多 不能找别人 首先这道题好像我自己找不到NIE的情况 很容易想到一个优化 如果一个数/2>另一个数 那么一定 ...

  6. POI2015题解

    POI2015题解 吐槽一下为什么POI2015开始就成了破烂波兰文题目名了啊... 咕了一道3748没写打表题没什么意思,还剩\(BZOJ\)上的\(14\)道题. [BZOJ3746][POI20 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

  9. BZOJ 4384: [POI2015]Trzy wieże

    4384: [POI2015]Trzy wieże Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 217  Solved: 61[Submit][St ...

随机推荐

  1. 一个简单的爆破 mysql 远程连接脚本(perl6)

    sub MAIN(Str $host) { use DBIish; my $file = open 'password.txt'; while $file.get -> $line { my $ ...

  2. C# Java 加密解密

    C# AES加密解密 public static string Encrypt(string key, string clearText) { byte[] clearBytes = Encoding ...

  3. 邮件伪造测试-Swaks

    1. 前言 在kali中自带一个邮件伪造工具Swaks,工具项目主页为 http://jetmore.org/john/code/swaks 2.基本用法: swaks --to --from --e ...

  4. 84.VMware Tools安装——设置共享文件

    一.安装VMware Tools 1.如图所示,点击安装 2.出现如下界面,将VMwareTools-9.6.2-1688356.tar.gz安装包复制到主文件夹下 3.输入命令tar -zxvf V ...

  5. GBDT+LR simple例子

    卧槽,本来猜GBDT获取的组合特征,需要自己去解析GBDT的树,scikit learn里面竟然直接调用apply函数就可以了 # 弱分类器的数目 n_estimator = 10 # 随机生成分类数 ...

  6. 日期时间设置 "2018-05-04T16:36:23.6341371+08:00" 格式

    using System;using System.Collections.Generic;using System.Globalization;using System.Text; namespac ...

  7. jpql和sql的区别

    项目使用jpa规范 其中既可使用面对对象查询(jpql语句) 又可使用原生sql查询; 1.(经后期验证,jpql都可以) 其中有一个区别是: jpql查询字段为空:  " cr.owner ...

  8. 蛮力法解决0_1背包问题新思路-——利用C语言位域类型

    废话不说了,直接上代码 #include<stdio.h> #include<math.h> #define N 5 //物品种类数目 #define CAPACITY 6 / ...

  9. Codeforces 2B The least round way(dp求最小末尾0)

    题目链接:http://codeforces.com/problemset/problem/2/B 题目大意: 给你一个nxn的矩形,找到一条从左上角到右下角的路径,使得该路径上所有数字的乘积的末尾0 ...

  10. 如何解决vuex因浏览器刷新数据消失,保持数据持久化问题?

    vuex的一个全局状态管理的插件,但是在浏览器刷新的时候,内存中的state会释放.通常的解决办法就是用本地存储的方式保存数据,然后再vuex初始化的时候再赋值给state,此过程有点麻烦.因此可以使 ...