【LG3241】[HNOI2015]开店
题面
题解
20pts
直接暴力统计即可,复杂度\(O(NQ)\)。
另20pts
我们考虑动态点分治。
怎么在原树上统计答案呢,我们对点\(x\),
预处理出其子节点数目\(s_0\),其子树内每个点到\(x\)的距离和\(s_1\),以及其子树内每个点到\(fa_x\)的距离和\(s_2\)。
则每次我们暴跳父亲,显然\(s_1[x]+\sum s_1[fa]-s_2[p]+(s_0[fa]-s_0[p])*dis(fa,x)\)就是树上与\(x\)的\(lca\)
为\(fa\)的所有点的距离之和,其中\(fa\)为\(p\)的父亲,\(p\)为从\(x\)不断跳父亲直到根,那么只要不断枚举\(fa\),并不断往上跳并维护答案就可以了。
然而上面只是为了方便理解,因为具体的计算不是这样的。我们对于\(x\)点内部的贡献可以直接计算,然后考虑往上跳。在上述的式子中如果一个点\(p\)有\(fa\),那么答案就要减去\(s_0[p]*dis(fa,x)+s_2[p]\),如果一个点不是\(x\)那么答案就要加上\(s_0[p]+dis(p,x)\),然后每一个点都要加上自己的\(sz_1\)。
按这个规律在跳的时候不断加就好了。
然后在点分树上维护这个东西就好了,正确性显然。
再对于每个年龄维护一个东西,复杂度\(O(20*Q\log n)\)。
100pts
其实上面讲得差不多了。
每个点维护一个\(vector\),对上述信息进行维护,将每个点的按年龄排序,统计距离的前缀和再分二分年龄即可。
时间复杂度\(O(Q\log^2 n)\),空间复杂度\(O(n\log n)\)。
代码
C++11真的爽
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
typedef long long ll;
const int INF = 1e9 + 5;
const int MAX_N = 1.5e5 + 5;
struct Graph { int to, cost, next; } e[MAX_N << 1]; int fir[MAX_N], e_cnt;
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; }
void Add_Edge(int u, int v, int w) { e[e_cnt] = {v, w, fir[u]}; fir[u] = e_cnt++; }
struct Node { int age, dis; ll sum; } ;
inline bool operator < (const Node &l, const Node &r) {
if (l.age == r.age) return l.dis == r.dis ? l.sum < r.sum : l.dis < r.dis;
else return l.age < r.age;
}
vector<Node> vec[2][MAX_N];
int pos[MAX_N], cnt, lg[MAX_N << 1], bin[20];
int md[20][MAX_N << 1], dep[MAX_N];
void dfs(int x, int f) {
md[0][pos[x] = ++cnt] = dep[x];
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (v == f) continue;
dep[v] = dep[x] + e[i].cost;
dfs(v, x);
md[0][++cnt] = dep[x];
}
}
int dis(int u, int v) {
int tmp = dep[u] + dep[v];
u = pos[u], v = pos[v];
if (u > v) swap(u, v);
int k = lg[v - u + 1];
return tmp - (min(md[k][u], md[k][v - bin[k] + 1]) << 1ll);
}
int fa[MAX_N], size[MAX_N], centroid, rmx, sz;
bool used[MAX_N];
void search_centroid(int x, int f) {
int mx = 0; size[x] = 1;
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (v == f || used[v]) continue;
search_centroid(v, x); size[x] += size[v];
mx = max(mx, size[v]);
}
mx = max(mx, sz - size[x]);
if (mx < rmx) centroid = x, rmx = mx;
}
void Div(int x) {
used[x] = 1;
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v]) continue;
rmx = sz = size[v];
centroid = v;
search_centroid(v, x);
fa[centroid] = x;
Div(centroid);
}
}
ll query(int x, int a) {
ll ans = 0;
for (int i = x; i; i = fa[i]) {
int t = lower_bound(vec[0][i].begin(), vec[0][i].end(), (Node){a, 0, 0})
- vec[0][i].begin() - 1;
ans += vec[0][i][t].sum + 1ll * t * dis(i, x);
}
for (int i = x; fa[i]; i = fa[i]) {
int t = lower_bound(vec[1][i].begin(), vec[1][i].end(), (Node){a, 0, 0})
- vec[1][i].begin() - 1;
ans -= vec[1][i][t].sum + 1ll * t * dis(fa[i], x);
}
return ans;
}
int N, Q, A, age[MAX_N];
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
clearGraph();
N = gi(), Q = gi(), A = gi();
for (int i = 1; i <= N; i++) age[i] = gi();
for (int i = 1; i < N; i++) {
int u = gi(), v = gi(), w = gi();
Add_Edge(u, v, w), Add_Edge(v, u, w);
}
dfs(1, 0);
bin[0] = 1; for (int i = 1; i < 20; i++) bin[i] = bin[i - 1] << 1;
for (int i = 1; bin[i] <= cnt; i++)
for (int j = 1; j + bin[i] - 1 <= cnt; j++)
md[i][j] = min(md[i - 1][j], md[i - 1][j + bin[i - 1]]);
for (int i = 2; i <= cnt; i++) lg[i] = lg[i >> 1] + 1;
sz = rmx = N;
search_centroid(1, 0);
Div(centroid);
for (int x = 1; x <= N; ++x)
for (int o = x; o; o = fa[o]) {
vec[0][o].push_back({age[x], dis(x, o), 0});
vec[1][o].push_back({age[x], dis(x, fa[o]), 0});
}
for (int x = 1; x <= N; ++x) {
for (int op = 0; op < 2; ++op) {
vec[op][x].push_back({-1, 0, 0});
vec[op][x].push_back({INF, 0, 0});
sort(vec[op][x].begin(), vec[op][x].end());
for (auto ite = vec[op][x].begin() + 1; ite != vec[op][x].end(); ++ite)
ite -> sum = (ite - 1) -> sum + ite -> dis;
}
}
for (ll ans = 0; Q--; ) {
int x = gi(), a = (ans + gi()) % A, b = (ans + gi()) % A;
if (a > b) swap(a, b);
printf("%lld\n", ans = query(x, b + 1) - query(x, a));
}
return 0;
}
【LG3241】[HNOI2015]开店的更多相关文章
- [HNOI2015]开店 树链剖分,主席树
[HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...
- 洛谷 P3241 [HNOI2015]开店 解题报告
P3241 [HNOI2015]开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想法当然非 ...
- [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)
4012: [HNOI2015]开店 Time Limit: 70 Sec Memory Limit: 512 MBSubmit: 2168 Solved: 947[Submit][Status] ...
- 【BZOJ4012】[HNOI2015]开店 动态树分治+二分
[BZOJ4012][HNOI2015]开店 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点 ...
- BZOJ4012 [HNOI2015]开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- bzoj 4012: [HNOI2015]开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- bzoj 4012: [HNOI2015]开店 主席树
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- BZOJ4012: [HNOI2015]开店【动态点分治】
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
随机推荐
- P3174 [HAOI2009]毛毛虫
题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...
- 巧用DNSlog实现无回显注入
测试一些网站的时候,一些注入都是无回显的,我们可以写脚本来进行盲注,但有些网站会ban掉我们的ip,这样我们可以通过设置ip代理池解决, 但是盲注往往效率很低,所以产生了DNSlog注入.具体原理如下 ...
- leetcode -50. Pow(x, n) Accepted
前言:其实之前自己也有了解关于算法数据结构的一点内容,但是都是用相应的开发工具来写相应的代码,今天面试的时候直接leetcode来写代码,还是用的体内根深蒂固的C和Java来解的题,毕竟目前没见支持O ...
- 微服务之数据同步Porter
Porter是一款数据同步中间件,主要用于解决同构/异构数据库之间的表级别数据同步问题. 背景 在微服务架构模式下深刻的影响了应用和数据库之间的关系,不像传统多个服务共享一个数据库,微服务架构下每个服 ...
- JS知识点整理(一)
前言 本文把平时的一些读书笔记和理解进行了整理归纳,包含一些易混淆.遗漏的知识点,也会配上一些例子,可能不是很完整,还会有点杂,但也许会有你需要的(目前先整理了一部分,笔记有点多,后续会持续更新). ...
- JS の 套路 I ~~
小扇在到新公司以后,发现.我的js都忘记了!! 下面总结一下在装配数据时候用到的一些小小的公式,希望像我这样的前端小菜B起到帮助叭叭叭叭叭~~~ I.查找想找到的 HTML 元素 * i.查找元素 v ...
- Oracle 实例管理
理解初始化参数文件实例由内存中构建它的参数来定义.许多参数(但不是全部)可以在启动后更改.有些参数在启动时就固定了,只能在关闭实例并再次启动时更改. 静态和动态参数文件参数文件由两类:静态参数文件(也 ...
- iOS笔记,开发经验总结【持续更新】
1. 设置navigationBar 背景颜色有色差, 原因:如果单纯的设置背景颜色也是有高斯模糊处理的效果,对纯色高斯模糊处理过后相当于纯色的70%(猜测)透明化处理,但是反正就是有色差 解决方法一 ...
- 832. Flipping an Image (5月22日 )
解答 class Solution { public: vector<vector<int>> flipAndInvertImage(vector<vector<i ...
- 解决win10安装MySQL数据库出现服务无法启动的问题
安装mysql的时候一直出现这个问题,在网上找了很多种方法,终于解决了这个问题. 我在官网下载的安装包解压后没有my.ini文件,需要自己添加(红字不要复制) [mysql]# 设置mysql客户端默 ...