BZOJ4012 HNOI2015开店(树链剖分+主席树)
考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑;询问某点到所有黑点的距离之和。
注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2。要求出上面的东西,depth[x]+depth[y]可以很简单的算出来,关键在于depth[lca(x,y)]。这一部分实质上是x到根的路径和y到根的路径重合的部分。那么我们可以树剖,在修改的时候,把该点到根的路径全部+1(其实是1单位,具体到每个点是其到父亲的那条边的长度),查询时查这个点到根的权值和就好了。
然后回到本题。无修改查询某个区间很容易想到主席树,那么按照点权从小到大染黑就是上面那个题,用主席树记录一下答案。每次需要在主席树上修改logn个区间,那么复杂度是log^2的。注意查询时不能下传标记,否则空间爆炸。
这个做法并没有用到度数<=3的性质,要用的话可以动态点分,写不动。
对着树剖和主席树的部分调了好长时间,感觉非常正确,最后发现离散化出问题了……没救。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 200010
int n,m,q,t=,a[N],c[N],p[N],b[N],deep[N];
int dfn[N],fa[N],top[N],id[N],size[N],son[N],cnt=;
long long lastans=,tot[N];
struct data{int to,nxt,len;
}edge[N<<];
int root[N],sum[N],sz[N];
struct data2{int l,r,tag;long long x;
}tree[N<<];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
bool cmp(const int&x,const int&y)
{
return a[x]<a[y];
}
void dfs1(int k)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=fa[k])
{
deep[edge[i].to]=deep[k]+edge[i].len;
fa[edge[i].to]=k;
dfs1(edge[i].to);
size[k]+=size[edge[i].to];
if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
}
}
void dfs2(int k,int from)
{
top[k]=from;id[k]=++cnt;dfn[cnt]=k;
if (son[k]) dfs2(son[k],from);
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=fa[k]&&edge[i].to!=son[k])
dfs2(edge[i].to,edge[i].to);
}
void add(int &k,int l,int r,int x,int y)
{
tree[++cnt]=tree[k];k=cnt;
tree[k].x+=sum[y]-sum[x-];
if (l==x&&r==y){tree[k].tag++;return;}
int mid=l+r>>;
if (y<=mid) add(tree[k].l,l,mid,x,y);
else if (x>mid) add(tree[k].r,mid+,r,x,y);
else add(tree[k].l,l,mid,x,mid),add(tree[k].r,mid+,r,mid+,y);
}
long long query(int k,int l,int r,int x,int y,int tag)
{
if (l==x&&r==y) return tree[k].x+1ll*(sum[y]-sum[x-])*tag;
tag+=tree[k].tag;
int mid=l+r>>;
if (y<=mid) return query(tree[k].l,l,mid,x,y,tag);
else if (x>mid) return query(tree[k].r,mid+,r,x,y,tag);
else return query(tree[k].l,l,mid,x,mid,tag)+query(tree[k].r,mid+,r,mid+,y,tag);
}
void modify(int i,int x)
{
while (x)
{
add(root[i],,n,id[top[x]],id[x]);
x=fa[top[x]];
}
}
long long getans(int r,int l,int x)
{
long long s=1ll*deep[x]*(sz[r]-sz[l])+tot[r]-tot[l];
while (x)
{
s-=query(root[r],,n,id[top[x]],id[x],)-query(root[l],,n,id[top[x]],id[x],)<<;
x=fa[top[x]];
}
return s;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4012.in","r",stdin);
freopen("bzoj4012.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),q=read(),m=read();
for (int i=;i<=n;i++) c[i]=a[i]=read(),b[i]=i;
sort(b+,b+n+,cmp);
sort(c+,c+n+);
int u=unique(c+,c+n+)-c;
for (int i=;i<n;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z),addedge(y,x,z);
}
dfs1();
dfs2(,);
cnt=;
for (int i=;i<=n;i++) sum[i]=sum[i-]+deep[dfn[i]]-deep[fa[dfn[i]]];
for (int i=;i<=n;i++)
{
int x=lower_bound(c+,c+u,a[b[i]])-c;
root[x]=root[x-];tot[x]=tot[x-];
modify(x,b[i]);tot[x]+=deep[b[i]];
while (a[b[i+]]==a[b[i]]) i++,modify(x,b[i]),tot[x]+=deep[b[i]];
sz[x]=i;
}
for (int i=;i<=q;i++)
{
int x=read(),w=read(),v=read();
int l=min((w+lastans)%m,(v+lastans)%m),r=max((w+lastans)%m,(v+lastans)%m);
l=lower_bound(c+,c+u,l)-c,r=upper_bound(c+,c+u,r)-c-;
lastans=getans(r,l-,x);
printf(LL,lastans);
}
return ;
}
BZOJ4012 HNOI2015开店(树链剖分+主席树)的更多相关文章
- dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448
4448: [Scoi2015]情报传递 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 588 Solved: 308[Submit][Status ...
- Codechef FIBTREE 树链剖分 主席树 LCA 二次剩余 快速幂
原文链接https://www.cnblogs.com/zhouzhendong/p/CC-FIBTREE.html 题目传送门 - CC-FIBTREE 题意 给定一个有 $n$ 个节点,初始点权都 ...
- BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...
- bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...
- BZOJ 4448: [Scoi2015]情报传递 树链剖分 主席树
4448: [Scoi2015]情报传递 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4448 Description 奈特公司是一个巨 ...
- [GDOI2016][树链剖分+主席树]疯狂动物城
题面 Description Nick 是只在动物城以坑蒙拐骗为生的狐狸,儿时受到偏见的伤害,放弃了自己的理想.他被兔子 Judy 设下圈套,被迫与她合作查案,而卷入意想不到的阴谋,历尽艰险后成为搭档 ...
- HDU 5111 Alexandra and Two Trees 树链剖分 + 主席树
题意: 给出两棵树,每棵树的节点都有一个权值. 同一棵树上的节点的权值互不相同,不同树上节点的权值可以相同. 要求回答如下询问: \(u_1 \, v_1 \, u_2 \, v_2\):询问第一棵树 ...
- 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治
LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...
- BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树
题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点 ...
随机推荐
- Crowdsourcing[智能辅助标注]
为了实现标注平台智能辅助标注的能力,即上传一个标注任务,开始不提供辅助任务,随着用户标注的进行,后台可以收集一部分的标记数据,然后开启模型训练,并接着提供模型服务功能.然后再收集数据,再不断的训练,然 ...
- CF1028G Guess the Numbers 构造、记忆化搜索
传送门 考虑如果我们当前可以询问\(x\)个数,还剩下\(q\)次询问机会,我们要怎么构造询问方式? 肯定会这么考虑: 找到一个尽可能大的\(P\)满足\([x,P]\)能在每一次能询问\(x\)个数 ...
- LOJ2538 PKUWC2018 Slay the Spire DP
传送门 不想放题面了,咕咕咕咕咕 这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和. 首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大 所以说在强化牌 ...
- Luogu3516 POI2011 Shift 构造
传送门 题意:给出一个长为$N$的排列,有两种操作:$A$:将最后一个数字放到第一个:$B$:将第三个数字放到第一个.一次性使用某种操作$k$次写作$kA$或$kB$,其中在$kA$中$k < ...
- aurora 64B/66B ip核设置与例程代码详解
见网页https://blog.csdn.net/u014586651/article/details/84349328 https://blog.csdn.net/u012135070/articl ...
- 重建索引解决mssql表查询超时的问题
表已有数据,150万+,执行一个group by 的查询出现超时,一个一个条件减少尝试,前几个where条件不超时,而在加上最后一个条件时就超时了. 分析表的索引建立情况:DBCC showconti ...
- kill方法
删除磁盘上的文件. 语法 Kill 路径名 所需的_路径名_参数是一个字符串表达式,指定要删除的一个或多个文件名. _Pathname_可能包括驱动器和目录或文件夹. 例子删除当前路径下的TXT文档 ...
- restfull环境搭建-helloword(三)
原文地址:http://only81.iteye.com/blog/1689537 This section creates a CRUD (Create, Read, Update, Delete) ...
- 如何新增一个ssh-key文件
前言 由于在公司有一个sshkey 在用,用于绑定公司的git code 仓库.那么在家要连上git hub 仓库,就也需要一个 ssh key .为了避免公司信息外露,所以还是新增一个ssh key ...
- python基础学习笔记(五)
字符串基本操作 所有标准的序列操作(索引.分片.乘法.判断成员资格.求长度.取最小值和最大值)对字符串同样适用,前面已经讲述的这些操作.但是,请注意字符串都是不可变的. 字符串的方法: 字符串从str ...