[COGS 2258][HZOI 2015]复仇的序幕曲
Description
你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言
当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深
他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平定了国内所有的不满
只有他一个人孤身逃了出来,而现在他组织了一只强大的军队,反攻的号角已经吹响
大战一触即发,作为他的机智又勇敢的指挥官,你必须要准确及时的完成他布置的任务
这个国家的布局是一棵树,每个城市都是树上的结点,其中每个结点上都有军队ai(人数)
树上的每条边有边权wi,表示通过这条边所需要的时间
当一个城市u受到攻击时,所有城市的军队都会同时向这个城市移动
阿凯蒂王子需要知道在时间T内,u城市最多聚集多少人
Input
第一行n,m,分别表示城市数目和询问次数
第二行有n个正整数,表示每个结点军队人数ai
以下n-1行每行描述树上的一条边的两个端点u,v和边权w
以下m行每行一个询问u,T
表示在时间T内,u城市最多聚集多少人
注意询问之间相互独立
Output
输出m行,每行一个数
表示询问的答案
Sample Input
5 5
3 7 1 7 4
2 1 9
3 1 6
4 2 5
5 3 1
5 1
4 3
1 1
1 4
4 2
Sample Output
5
7
3
3
7
Hint
n<=80000,m<=80000
边权和军队人数均<=1000
题解
首先,对于题目要求 $dist(u, v) \leq k$ ,我们从 $u$ 在点分树向上跳的时候,第一次处理到含点 $v$ 的重心,那么这个重心就是 $lca(u, v)$ ,我们对这个 $lca$ 进行处理。
由于满足上式,所以 $dist(u, lca)+dist(v, lca) \leq k$ 等价于若点 $v$ 满足 $dist(v, lca) \leq k-dist(u, lca)$ 那么显然 $v$ 是满足 $u$ 。
那么我们可以在每个节点上建一棵平衡树,维护以其为重心的子树中 $dist(v, lca)$ 的值,显然统计答案就是平衡树中 $\leq k-dist(u, lca)$ 的个数。
按照套路,为了防止重复计算,我们需要减去会在这个重心的父亲处重复计算的值。记在点分树中 $u$ 节点的父亲为 $fa_u$ ,所以我们再开一个平衡树来存 $dist(fa_{lca}, v)$ ,额外减去的就是第二棵平衡树中 $\leq k-dist(fa_{lca}, u)$ 的个数。
//It is made by Awson on 2018.1.19
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
using namespace std;
const int N = ;
const int INF = ~0u>>;
void read(int &x) {
char ch; bool flag = ;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || ); ch = getchar());
for (x = ; isdigit(ch); x = (x<<)+(x<<)+ch-, ch = getchar());
x *= -*flag;
}
void write(int x) {
if (x > ) write(x/);
putchar(x%+);
} int val[N+], n, m, u, v, fa[N+], last, c;
struct tt {int to, next, cost; }edge[(N<<)+];
int path[N+], top;
void add(int u, int v, int c) {
edge[++top].to = v, edge[top].next = path[u], edge[top].cost = c, path[u] = top;
}
struct Treap {
int root[N+], key[N*+], val[N*+], sum[N*+], lev[N*+], ch[N*+][], pos;
void newnode(int &o, int keyy, int vall) {
o = ++pos;
key[o] = keyy, sum[o] = val[o] = vall, lev[o] = rand(), ch[o][] = ch[o][] = ;
}
void pushup(int o) {sum[o] = sum[ch[o][]]+sum[ch[o][]]+val[o]; }
void rotate(int &o, int kind) {
int x = ch[o][!kind];
ch[o][!kind] = ch[x][kind];
ch[x][kind] = o;
o = x;
}
void insert(int &o, int keyy, int vall) {
if (!o) {newnode(o, keyy, vall); return; }
sum[o] += vall; int kind = keyy >= key[o];
insert(ch[o][kind], keyy, vall);
if (lev[ch[o][kind]] < lev[o]) rotate(o, !kind), pushup(ch[o][!kind]), pushup(o);
}
int query(int o, int keyy) {
if (!o) return ;
if (keyy >= key[o]) return sum[ch[o][]]+val[o]+query(ch[o][], keyy);
return query(ch[o][], keyy);
}
}T1, T2;
namespace LCA {
int log2[(N<<)+], bin[], f[(N<<)+][], dfn[N+], tim;
void dfs(int o, int cost) {
f[dfn[o] = ++tim][] = cost;
for (int i = path[o]; i; i = edge[i].next)
if (!dfn[edge[i].to]) dfs(edge[i].to, cost+edge[i].cost), f[++tim][] = cost;
}
int query(int x, int y) {
if (dfn[x] > dfn[y]) Swap(x, y); int lim = log2[dfn[y]-dfn[x]+];
return Min(f[dfn[x]][lim], f[dfn[y]-bin[lim]+][lim]);
}
int dist(int x, int y) {return f[dfn[x]][]+f[dfn[y]][]-(query(x, y)<<); }
void main() {
bin[] = , log2[] = -;
for (int i = ; i <= (n<<); i++) log2[i] = log2[i>>]+;
for (int i = ; i <= ; i++) bin[i] = bin[i-]<<;
dfs(, );
for (int t = ; t <= log2[n<<]; t++) for (int i = ; i+bin[t]- <= (n<<); i++) f[i][t] = Min(f[i][t-], f[i+bin[t-]][t-]);
}
}
namespace Point_divide {
int size[N+], mx[N+], minsize, root, vis[N+];
void get_root(int o, int pa, int fa) {
mx[o] = Max(mx[o], size[pa]-size[o]);
if (mx[o] < minsize) minsize = mx[o], root = o;
for (int i = path[o]; i; i = edge[i].next)
if (edge[i].to != fa && !vis[edge[i].to]) get_root(edge[i].to, pa, o);
}
void get_size(int o, int fa) {
size[o] = , mx[o] = ;
for (int i = path[o]; i; i = edge[i].next)
if (edge[i].to != fa && !vis[edge[i].to]) {
get_size(edge[i].to, o);
size[o] += size[edge[i].to];
if (size[edge[i].to] > mx[o]) mx[o] = size[edge[i].to];
}
}
void get_insert(int o, int pa, int da, int fa, int cost) {
T1.insert(T1.root[da], cost, val[o]); if (pa) T2.insert(T2.root[da], LCA::dist(pa, o), val[o]);
for (int i = path[o]; i; i = edge[i].next) if (edge[i].to != fa && !vis[edge[i].to]) get_insert(edge[i].to, pa, da, o, cost+edge[i].cost);
}
void work(int o, int pa) {
minsize = INF; get_size(o, ), get_root(o, o, ); vis[root] = , fa[root] = pa; int rt = root;
T1.insert(T1.root[root], , val[root]); if (pa) T2.insert(T2.root[root], LCA::dist(pa, root), val[root]);
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to]) get_insert(edge[i].to, pa, root, , edge[i].cost);
for (int i = path[root]; i; i = edge[i].next)
if (!vis[edge[i].to]) work(edge[i].to, rt);
}
void main() {work(, ); }
} int query(int o, int k) {
int ans = ;
for (int x = o; x; x = fa[x]) {
ans += T1.query(T1.root[x], k-LCA::dist(x, o));
if (fa[x]) ans -= T2.query(T2.root[x], k-LCA::dist(fa[x], o));
}
return ans;
}
void work() {
srand(time()); read(n), read(m);
for (int i = ; i <= n; i++) read(val[i]);
for (int i = ; i < n; i++) {read(u), read(v), read(c); add(u, v, c), add(v, u, c); }
LCA::main(); Point_divide::main();
while (m--) {
read(u), read(v); writeln(query(u, v));
}
}
int main() {
work();
return ;
}
[COGS 2258][HZOI 2015]复仇的序幕曲的更多相关文章
- [HZOI 2015]复仇的序幕曲
[题目描述] 你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言 当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深 他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平定了国内所 ...
- COGS 2580. [HZOI 2015]偏序 II
COGS 2580. [HZOI 2015]偏序 II 题目传送门 题目大意:给n个元素,每个元素有具有4个属性a,b,c,d,求i<j并且ai<aj,bi<bj,ci<cj, ...
- cogs 2123. [HZOI 2015] Glass Beads
2123. [HZOI 2015] Glass Beads ★★★ 输入文件:MinRepresentations.in 输出文件:MinRepresentations.out 简单对比时 ...
- cogs 2320. [HZOI 2015]聪聪的世界题解
2320. [HZOI 2015]聪聪的世界 时间限制:6 s 内存限制:512 MB [题目描述] 背景: 聪聪的性取向有问题. 题目描述: 聪聪遇到了一个难题: 给出一个序列a1…an,完成以 ...
- COGS 2188. [HZOI 2015] Math 题解
题目描述: 给定n个数X1-Xn,求下面式子的值(整数部分): n<=107,xi<=109且互不相同. 分析: 其实一开始看见这道题我也吓傻了,k这么大,再说我又是数论鶸渣,打死也不 ...
- [COGS 2287][HZOI 2015]疯狂的机器人
Description 题库链接 现在在二维平面内原点上有一只机器人,他每次可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格).机器人不能走到横坐标是负数或者纵坐标是负数的点上. 给 ...
- cogs 2355. [HZOI 2015] 有标号的DAG计数 II
题目分析 来自2013年王迪的论文<浅谈容斥原理> 设\(f_{n,S}\)表示n个节点,入度为0的点集恰好为S的方案数. 设\(g_{n,S}\)表示n个节点,入度为0的点集至少为S的方 ...
- COGS 2280. [HZOI 2015]树白黑
★★ 输入文件:B_Tree.in 输出文件:B_Tree.out 简单对比时间限制:2 s 内存限制:512 MB [题目描述] 给定一棵有根树,树根为1,一开始这棵树所有节点均为白 ...
- COGS 2294. [HZOI 2015] 释迦
额,其实就是裸的三模数NTT,上一篇已经说过了 哦,还有一个就是对乘起来炸long long的数取模,用long double之类的搞一下就好,精度什么的,,(看出题人心情??) #include&l ...
随机推荐
- spring框架学习笔记5:SpringAOP示例
1.导包: 导入spring中的这两个包 再导入其他包(网上下载): 2.准备目标对象: package service; public class UserServiceImpl implement ...
- 团队作业5-测试与发布(AIpha版本)
对于已完成的项目我们进行了诸多测试,找到了少许bug,对着这些bug我们在改进的基础上提出了新的目标. 1,测试环境:个人笔记本.个人台式机.环境windows7.网络校园网加移动vpn,浏览器360 ...
- Beta预备
团队名称:稳住!我们能赢 Beta预备: 讨论组长是否重选的议题和结论 项目组长可以说是一个团队的灵魂和核心.一个好的领导者可以激发团队成员的工作热情,提高开发效率,保质保量的完成工作.虽然在Alph ...
- initializer element is not a compile-time constant
初始化一个全局变量或static变量时,只能用常量赋值,不能用变量赋值! 如下就会报这个错误(KUIScreenWidth)是变量 static CGFloat const topButtonWidt ...
- Java ftp 上传文件和下载文件
今天同事问我一个ftp 上传文件和下载文件功能应该怎么做,当时有点懵逼,毕竟我也是第一次,然后装了个逼,在网上找了一段代码发给同事,叫他调试一下.结果悲剧了,运行不通过.(装逼失败) 我找的文章链接: ...
- 使用caffe训练mnist数据集 - caffe教程实战(一)
个人认为学习一个陌生的框架,最好从例子开始,所以我们也从一个例子开始. 学习本教程之前,你需要首先对卷积神经网络算法原理有些了解,而且安装好了caffe 卷积神经网络原理参考:http://cs231 ...
- python 关键字的操作
声明:本文章默认使用的是python 3.6.1 1.要想当个牛逼的程序员,就要精通各种hello world的写法,当然,我不牛逼,只能用python去写^..^! print("Hell ...
- Java+Maven+selenium+testing+reportNG自动化测试框架
最近公司新出了一个产品,需要搭建自动化测试框架,这是一个学以至用的好机会,跟上级申请后,决定搭建一个java自动化测试框架. Java自动化测试对我来讲可以说不难不易,因为java是我大学在校四年学的 ...
- netty : NioEventLoopGroup 源码分析
NioEventLoopGroup 源码分析 1. 在阅读源码时做了一定的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限.为了方便 IDE 查看.跟踪.调试 代码,所以在 github ...
- 第1章 什么是TCP-IP
第1章 什么是TCP-IP 什么是网络 网络是计算机或类似计算机的设备之间通过常用传输介质进行通信的集合.通常情况下,传输介质是绝缘的金属导线, 它用来在计算机之间携带电脉冲,介质也可以是电话线,甚至 ...