洛谷P3241 开店
题意:紫妹和幽香是17岁的少女,喜欢可爱的东西。
给定一棵树,有点权,边权。每次求所有权值在[l, r]范围内的点到点x的距离和。强制在线。
解:动态点分治怎么搞啊......
一开始想的是权值的限制直接外层权值线段树就行了,关键是怎么批量求距离。
jxl想的是树上莫队的方法,括号序列。然后发现当x和y在不同子树的时候,x -> lca的距离是负的。
然后考虑lca。距离是d[x] + d[y] - 2d[lca],前面两个都好求,主要是第三项。
稍稍思考一下,lca只可能是x到根路径上的点。每个点作为lca的次数就是siz - siz[son]
所以可以转为计算每条边的贡献。每条边的贡献就是它下面的子树大小。这样就可以做了。
具体来说,d[x] * cnt和∑d[y]可以用两个前缀和数组求出。以离散化后的权值为下标。
然后建一个以权值为版本的主席树,线段树上维护的是DFS序的该点的父边的计算次数。
可以发现,按照权值我们每插入一个点,就要对它到根的路径进行修改。查询的时候也是查询x到根的路径。所以我们必须写树剖了>_<
主席树区间加区间查,使用标记永久化。
然后发现我之前以为的标记永久化都是假的......
具体来说,给一个区间加的时候,它途中经过的区间都要加上相应的值,而标记只打在最后的区间。
查询的时候,沿途记录标记数量。到终点的时候,用终点的sum + 区间Val * 标记数量即可。
如果修改在查询上面,那么你会把标记记录下来,最后在终点区间加上。
如果修改在下,那么你终点区间的sum已经加了那一次修改的影响。
然后这道毒瘤SB题就这样A了...时间复杂度nlog2n。
#include <cstdio>
#include <algorithm> typedef long long LL;
const int N = , lm = 1e9, M = ; struct Edge {
int nex, v, len;
}edge[N << ]; int tp; struct Node {
int val, p;
inline bool operator <(const Node &w) const {
return val < w.val;
}
}node[N]; int e[N], n, top[N], son[N], fa[N], pos[N], num, siz[N], X[N], deep[N], Sum[N], id[N], val2[N], tot, rt[N], val[N];
LL Val[M], d[N], exVal[N];
int ls[M], rs[M], exsum[N], tag[M]; inline void add(int x, int y, int z) {
tp++;
edge[tp].v = y;
edge[tp].len = z;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void DFS_1(int x, int f) { // siz fa d son
fa[x] = f;
siz[x] = ;
deep[x] = deep[f] + ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f) {
continue;
}
d[y] = d[x] + edge[i].len;
val2[y] = edge[i].len;
DFS_1(y, x);
siz[x] += siz[y];
if(siz[y] > siz[son[x]]) {
son[x] = y;
}
}
return;
} void DFS_2(int x, int f) { // pos top
top[x] = f;
pos[x] = ++num;
id[num] = x;
if(son[x]) {
DFS_2(son[x], f);
}
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa[x] || y == son[x]) {
continue;
}
DFS_2(y, y);
}
return;
} void Add(int x, int &y, int L, int R, int l, int r) {
if(!y || y == x) {
y = ++tot;
Val[y] = Val[x];
tag[y] = tag[x];
ls[y] = ls[x];
rs[y] = rs[x];
//printf("new %d [%d %d] val = %lld \n", y, l, r, Val[y]);
}
Val[y] += Sum[std::min(R, r)] - Sum[std::max(L, l) - ];
//printf("val %d = %lld += (%d %d) %d \n", y, Val[y], std::min(R, r), std::max(L, l) - 1, Sum[std::min(R, r)] - Sum[std::max(L, l) - 1]);
if(L <= l && r <= R) {
tag[y]++;
return;
}
int mid = (l + r) >> ;
if(L <= mid) {
Add(ls[x], ls[y], L, R, l, mid);
}
if(mid < R) {
Add(rs[x], rs[y], L, R, mid + , r);
}
return;
} inline void insert(int x, int id) {
while(x) {
//printf("id = %d \n", id);
Add(rt[id - ], rt[id], pos[top[x]], pos[top[x]] + (deep[x] - deep[top[x]]), , n);
x = fa[top[x]];
}
return;
} LL Ask(int x, int y, int L, int R, int l, int r, int tagx, int tagy) {
if(L <= l && r <= R) {
return Val[y] - Val[x] + 1ll * (tagy - tagx) * (Sum[r] - Sum[l - ]);
}
tagx += tag[x];
tagy += tag[y];
int mid = (l + r) >> ;
LL ans = ;
if(L <= mid) {
ans += Ask(ls[x], ls[y], L, R, l, mid, tagx, tagy);
}
if(mid < R) {
ans += Ask(rs[x], rs[y], L, R, mid + , r, tagx, tagy);
}
return ans;
} LL ask(int l, int r, int x) {
LL ans = ;
while(x) {
LL t = Ask(rt[l - ], rt[r], pos[top[x]], pos[top[x]] + (deep[x] - deep[top[x]]), , n, , );
ans += t;
x = fa[top[x]];
}
return ans;
} int main() { //freopen("in.in", "r", stdin);
//freopen("my.out", "w", stdout); int q, A;
scanf("%d%d%d", &n, &q, &A);
for(int i = ; i <= n; i++) {
scanf("%d", &val[i]);
val[i]++;
node[i].p = i;
X[i] = val[i];
}
for(int i = , x, y, z; i < n; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
// prework DFS_1(, );
DFS_2(, );
std::sort(X + , X + n + );
int temp = std::unique(X + , X + n + ) - X - ;
for(int i = ; i <= n; i++) {
val[i] = std::lower_bound(X + , X + temp + , val[i]) - X;
node[i].val = val[i];
exsum[val[i]]++;
exVal[val[i]] += d[i];
}
for(int i = ; i <= temp; i++) {
exsum[i] += exsum[i - ];
exVal[i] += exVal[i - ];
}
for(int i = ; i <= n; i++) {
Sum[i] = Sum[i - ] + val2[id[i]];
}
std::sort(node + , node + n + );
for(int i = ; i <= n; i++) {
insert(node[i].p, node[i].val);
} LL lastans = ;
for(int i = , x, y, z; i <= q; i++) {
scanf("%d%d%d", &x, &y, &z);
int l = (y + lastans) % A + ;
int r = (z + lastans) % A + ;
if(l > r) {
std::swap(l, r);
}
l = std::lower_bound(X + , X + temp + , l) - X;
r = std::upper_bound(X + , X + temp + , r) - X - ;
if(l > r) {
lastans = ;
printf("%lld\n", lastans);
}
else {
LL t = ask(l, r, x);
lastans = 1ll * d[x] * (exsum[r] - exsum[l - ]) + (exVal[r] - exVal[l - ]);
lastans -= t * ;
printf("%lld\n", lastans);
}
} return ;
}
AC代码
洛谷P3241 开店的更多相关文章
- 洛谷 P3241 [HNOI2015]开店 解题报告
P3241 [HNOI2015]开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想法当然非 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP
题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...
- 洛谷P1710 地铁涨价
P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交 讨论 题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...
- 洛谷P1371 NOI元丹
P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交 讨论 题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...
- 洛谷P1538迎春舞会之数字舞蹈
题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同学们决定排出——“数字舞蹈 ...
- 洛谷八月月赛Round1凄惨记
个人背景: 上午9:30放学,然后因为学校举办读书工程跟同学去书城选书,中午回来开始打比赛,下午又回老家,中间抽出一点时间调代码,回家已经8:50了 也许是7月月赛时“连蒙带骗”AK的太幸运然而因同学 ...
随机推荐
- 2017-2018 Exp7 网络欺诈技术防范 20155214
目录 Exp7 网络欺诈技术防范 实验内容 信息收集 知识点 Exp7 网络欺诈技术防范 实验内容 实验环境 主机 Kali 靶机 Windows 10 实验工具 平台 Metaploit 信息收集 ...
- 20155301PC平台逆向破解
20155301PC平台逆向破解 1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码 NOP:NOP指令即"空指令".执行到NOP指令时,CPU什么也不做,仅仅当 ...
- 20155308 《网络攻防》 Exp3 免杀原理与实践
20155308 <网络攻防> Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 基于特征来检测:恶意代码中一般会有一段有较明显特征的代码也就是特征码,如果杀毒软件检测 ...
- JavaEE笔记(十一)
Spring beans使用参数占位符(JDBC配置读取示例) beans.xml配置文件 <?xml version="1.0" encoding="UTF-8& ...
- 页面弹出全屏浮层或遮罩时,禁止底层body滚动
· 解决方法 针对弹出的浮层的 touchmove事件,添加阻止浏览器默认行为. $('.mask-wrapper').on('touchmove', function (event) { // 监听 ...
- [CF1083F]The Fair Nut and Amusing Xor[差分+同余分类+根号分治+分块]
题意 给定两个长度为 \(n\) 的序列 \(\{a_i\}\) 与 \(\{b_i\}\),你需要求出它们的相似度.,我们定义这两个序列的相似度为将其中一个序列转化为另一个序列所需的最小操作次数.一 ...
- mpvue两小时,产出一个《点钞辅助工具》小程序
CoffeeScript,Pug,Sass使用 以下内容门槛较高,如看不懂或觉得需要继续了解,结尾处放置了原视频流程与GitHub地址,欢迎琢磨与Star,谢谢. 文章不做技术语法解读,如不清楚,请前 ...
- Redis简介、安装、配置、启用学习笔记
前一篇文章有介绍关系型数据库和非关系型数据库的差异,现在就来学习一下用的较广的非关系型数据库:Redis数据库 Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-v ...
- Linux+Nginx+Asp.net Core及守护进程部署
上篇<Docker基础入门及示例>文章介绍了Docker部署,以及相关.net core 的打包示例.这篇文章我将以oss.offical.site站点为例,主要介绍下在linux机器下完 ...
- OD之去除nag弹窗(四)
在某些方面,一个软件如果没有注册的话,老是会弹出烦人的注册弹窗,就如下图一样: 出现了两次弹窗,开始一次,关闭后又一次,老办法,拖进OD进行分析;不过看出程序很简单,就出现了messagebox的调用 ...