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. 分析: 树链剖分,对每个类型的点 ...
随机推荐
- async源码学习 - 全部源码
因为工作需要,可能我离前端走远了,偏node方向了.所以异步编程的需求很多,于是乎,不得不带着学习async了. 我有个习惯,用别人的东西之前,喜欢稍微搞明白点,so就带着看看其源码. github: ...
- 开源HTTP解析器---http-parser和fast-http
由于项目中遇到需要发送http请求,然后再解析接收到的响应.大概在网上搜索了一下,有两个比较不错,分别是http-parser和fast-http. http-parser是由C编写的工具:fast- ...
- oracle 记录被另一个用户锁住
第一步:查询处用户,被锁表名,sessionID select b.owner,b.object_name,l.session_id,l.locked_modefrom v$locked_object ...
- curl发送json格式数据
php的curl方法详细的见官方手册. curl_setopt用法: http://www.php.net/manual/en/function.curl-setopt.php <?php $ ...
- DNS 协议
DNS 入门 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务.它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS 使用 T ...
- SQL SERVER中DBLINK的实现
exec sp_addlinkedserver 'CantennFlexPsApp' , '' , 'SQLOLEDB' , '目标数据库的IP' exec sp_addlinkedsrvlogin ...
- 控制反转IOC与依赖注入DI - 理论篇
学无止境,精益求精 十年河东十年河西,莫欺少年穷 昨天是五一小长假归来上班的第一天,身体疲劳,毫无工作热情.于是就看看新闻,喝喝茶,荒废了一天 也就在昨天,康美同事张晶童鞋让我学习下IOC的理论及实现 ...
- C# 全屏坐标及区域坐标获取。自定义光标及系统光标描边捕捉显示。
最近手头工作比较轻松了一点就继续研究和完善之前的录屏软件,使用AForge最大的问题在于:最原始的只能够录全屏,而自定义的录屏需要更改非常多的细节:like follows: 1.需要支持区域化录屏: ...
- js怎么将 base64转换成图片
//获取数组最后一个元素 let hasFiles = files[Object.keys(files).pop()] // 参考上面的图片 let file = hasFiles.url let n ...
- 四则运算coding
https://coding.net/u/ztf1641429293/p/sizeyunshuan/git/blob/master/Sizenyunsuan.java