BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)
讲得好啊
主席树区间修改了,每一次遇到整区间就打永久化标记(不下传,访问的时候沿路径上的标记算答案)然后returnreturnreturn,那么每修改一次只会访问到lognlognlogn个节点,再加上每个点要在树链上修改lognlognlogn次,所以空间复杂度O(nlog2n)O(nlog^2n)O(nlog2n),实测开O(n∗50)O(n*50)O(n∗50)能过…
各个sum都要开longlong啊,毁一生
CODE
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &num) {
char ch; int flg = 1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int MAXN = 150005;
const int MAXNN = MAXN*50;
int n, q, A, fir[MAXN], cnt;
struct edge { int to, nxt, w; }e[MAXN<<1];
inline void add(int u, int v, int wt) {
e[cnt] = (edge){ v, fir[u], wt }, fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], wt }, fir[v] = cnt++;
}
struct node {
int x, id;
node() {}
node(int xx, int ii):x(xx), id(ii){}
inline bool operator <(const node &o)const {
return x == o.x ? id < o.id : x < o.x;
}
}a[MAXN];
LL sumE[MAXN], dis[MAXN], sumD[MAXN];
int son[MAXN], sz[MAXN], top[MAXN], tmr, dfn[MAXN], fa[MAXN];
void dfs(int u, int ff) {
fa[u] = ff; sz[u] = 1;
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != ff) {
dis[v] = dis[u] + e[i].w;
dfs(v, u), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; dfn[u] = ++tmr;
sumE[tmr] = dis[u] - dis[fa[u]];
if(son[u]) dfs2(son[u], tp);
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != fa[u] && v != son[u])
dfs2(v, v);
}
int ch[MAXNN][2], tim[MAXNN], tot, rt[MAXN]; LL sum[MAXNN];
inline void Newnode(int i, int p) { ch[i][0] = ch[p][0], ch[i][1] = ch[p][1], sum[i] = sum[p], tim[i] = tim[p]; }
void modify(int &i, int l, int r, int L, int R) {
Newnode(++tot, i);
if(L == l && r == R) { ++tim[i = tot]; return; }
sum[i = tot] += sumE[R] - sumE[L-1];
int mid = (l + r) >> 1;
if(R <= mid) modify(ch[i][0], l, mid, L, R);
else if(L > mid) modify(ch[i][1], mid+1, r, L, R);
else modify(ch[i][0], l, mid, L, mid), modify(ch[i][1], mid+1, r, mid+1, R);
}
inline void Modify(int &r, int x) { while(x) modify(r, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]]; }
LL query(int i, int l, int r, int L, int R) {
LL res = (sumE[R] - sumE[L-1]) * tim[i];
if(L == l && r == R) return res + sum[i];
int mid = (l + r) >> 1;
if(R <= mid) return res + query(ch[i][0], l, mid, L, R);
else if(L > mid) return res + query(ch[i][1], mid+1, r, L, R);
return res + query(ch[i][0], l, mid, L, mid) + query(ch[i][1], mid+1, r, mid+1, R);
}
LL Query(int r, int x) { LL res = 0; while(x) res += query(r, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]]; return res; }
int main () {
read(n), read(q), read(A);
for(int i = 1; i <= n; ++i)
read(a[i].x), a[i].id = i;
sort(a + 1, a + n + 1);
memset(fir, -1, sizeof fir);
for(int i = 1, x, y, z; i < n; ++i)
read(x), read(y), read(z), add(x, y, z);
dfs(1, 0), dfs2(1, 1);
for(int i = 1; i <= n; ++i)
sumE[i] += sumE[i-1], sumD[i] = sumD[i-1] + dis[a[i].id];
for(int i = 1; i <= n; ++i) Modify(rt[i]=rt[i-1], a[i].id);
LL ans = 0, L, R, x;
while(q--) {
read(x), read(L), read(R);
L = (L + ans) % A, R = (R + ans) % A;
if(L > R) swap(L, R);
L = lower_bound(a + 1, a + n + 1, node(L, 0)) - a;
R = upper_bound(a + 1, a + n + 1, node(R, n)) - a - 1;
ans = dis[x] * (R-L+1) + (sumD[R] - sumD[L-1]) - (Query(rt[R], x) - Query(rt[L-1], x)) * 2;
printf("%lld\n", ans);
}
}
BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)的更多相关文章
- bzoj 4012: [HNOI2015]开店 主席树
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- bzoj 4012: [HNOI2015]开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ 4012 HNOI2015 开店 树的边分治+分治树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012 题意概述:给出一颗N点的树,保证树上所有点的度不超过3,树上每个点有权值,每条边有权 ...
- BZOJ 4012 [HNOI2015]开店 (树分治+二分)
题目大意: 给你一棵树,边有边权,点有点权,有很多次询问,求点权$\in[l,r]$的所有节点到某点$x$的距离之和,强制在线 感觉这个题应该放在动态点分之前做= = 套路方法和动态点分是一样的 每次 ...
- 【BZOJ】4012: [HNOI2015]开店
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012 给出一个$n$个点的树,树上每一个点都有一个值$age$,每条边都有边权,每次查询一 ...
- bzoj 3065: 带插入区间K小值 替罪羊树 && AC300
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1062 Solved: 253[Submit][Status] Des ...
- HDU 1754 - I Hate It & UVA 12299 - RMQ with Shifts - [单点/区间修改、区间查询线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Time Limit: 9000/3000 MS (Java/Others) Memory Li ...
- 【poj2104-求区间第k大数(不修改)】主席树/可持续化线段树
第一道主席树~然而是道比较水的...因为它不用修改... 转载一个让我看懂的主席树的讲解吧:http://blog.csdn.net/regina8023/article/details/419106 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
随机推荐
- poj2406(求字符串的周期,kmp算法next数组的应用)
题目链接:https://vjudge.net/problem/POJ-2406 题意:求出给定字符串的周期,和poj1961类似. 思路:直接利用next数组的定义即可,当没有周期时,周期即为1. ...
- Python中的with语句(上下文管理协议)
在平时工作中总会有这样的任务,它们需要开始前做准备,然后做任务,然后收尾清理....比如读取文件,需要先打开,读取,关闭 这个时候就可以使用with简化代码,很方便 1.没有用with语句 f = o ...
- 关于@service、@controller和@transactional 在spring中的位置说明
Spring容器优先加载由ServletContextListener(对应applicationContext.xml)产生的父容器,而SpringMVC(对应mvc_dispatcher_serv ...
- Vue路由传参及传参后刷新导致参数消失处理
项目功能需要,要从列表页跳转到第三方提供的URL上(这里第三方页面我是通过iframe引入在详情页,目的是点击返回时可以通过keepAlive让列表页不刷新,如果不通过iframe直接跳第三方链接,那 ...
- HTTP协议探究(三):HTTPS
一 复习与目标 1 复习 代理:转发通信数据(一般协议不变,作为中间人,可对报文进行过滤修改) 网关:转发通信数据(协议改变,作为资源拥有者) 隧道:转发通信数据(协议不变,作为管道,不对报文进行过滤 ...
- Linux常用命令(自用)
1 抓包 tcpdump port 5060 and host 192.168.1.180 tcpdump -i ethx -w 1.pcap -s 0 2. 查看硬盘使用情况 df ./ 3.查看进 ...
- scala的泛型浅析
1. scala泛型浅析 package com.dtspark.scala.basics /** * 1,scala的类和方法.函数都可以是泛型. * * 2,关于对类型边界的限定分为上边界和下边界 ...
- scala中ClassOf、asInstenceOf、isInstanceOf三个预定义方法分析
classOf.isInstanceOf.asInstanceOf三个预定义方法分析 Scala的三个预定义(predefined)方法,我们经常用到:它们用来感觉很简单, 但是里面还是隐藏了一些细节 ...
- JavaScript 的查询机制——LHS 与 RHS
JavaScript 引擎在查找一个变量的时候,有两种查找机制:LHS 和 RHS. RHS 的查询是简单地查找到某个变量的值,而 LHS 则是试图找到变量的容器的本身. 一个简单的例子:当我们执行 ...
- JAVA 内存模型(主内存,工作内存)
JVM将内存组织为主内存和工作内存两个部分. 主内存是所有的线程所共享的,主要包括本地方法区和堆. 每个线程都有一个工作内存不是共享的,工作内存中主要包括两个部分: 1:一个是属于该线程私有的栈; 2 ...