博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Loj #6073.「2017 山东一轮集训 Day5」距离
阅读量:6528 次
发布时间:2019-06-24

本文共 2411 字,大约阅读时间需要 8 分钟。

Loj #6073.「2017 山东一轮集训 Day5」距离

Description

给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\),设$ path(u,v) \(表示\) u$ 到 $v \(的路径,\)dist(u,v) \(表示\) u$ 到\(v\) 的距离,希望你求出

img

Input

第一行一个整数 \(type =0/1\)表示这个测试点的数据类型。

第二行两个整数 \(n,q\)
接下来$ n−1$ 行,每行三个整数 \(ui,vi,ci,\)代表树上有一条连接$ ui,vi$ 的权值为$ci $的边。
接下来一行 \(n\) 个正整数表示给定的排列 p。
接下来 \(q\) 行,每行三个整数 \(u′,v′,k′\),记lastAns 为上一次询问的答案,假如这是第一次则\(lastAns=0\),那么这个询问对应的\(u,v,k\) 满足:
img

思路还是比较妙啊。

题目的难点在于求一个点与一个点集的\(lca\)深度之和。我们可以将点集中的每个点到根的路径上的标记都\(+1\)。询问点\(k\)到这个点集的\(lca\)深度和的时候我们就可以询问该点到根路径上的所有边权与标记的乘积之和。

由于是询问\((a,b)\)路径上的信息,我们就用主席树维护,询问的时候做差分。对于一个节点\(a\),它的信息由\(fa_a\)继承下来,再加上\(p_a\)的信息就好了。

考试时不会,写的虚树,常数大到自闭。

[HNOI2015]开店 的主席树做法也是基于这个原理的。

代码:

#include
#define ll long long#define N 200005using namespace std;inline ll Get() {ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}int n,m,type;int p[N];ll pre[N];ll ans;struct road { int to,next; ll d;}s[N<<1];int h[N],cnt;void add(int i,int j,ll d) {s[++cnt]=(road) {j,h[i],d};h[i]=cnt;}ll sum_dis[N];int size[N],son[N];int fa[N],top[N],dep[N];ll dis[N];void dfs(int v) { size[v]=1; for(int i=h[v];i;i=s[i].next) { int to=s[i].to; if(to==fa[v]) continue ; dep[to]=dep[v]+1; dis[to]=dis[v]+s[i].d; fa[to]=v; dfs(to); size[v]+=size[to]; if(size[son[v]]
r||rx
>1; Modify(tr[v].ls,tr[old].ls,lx,mid,l,r,f); Modify(tr[v].rs,tr[old].rs,mid+1,rx,l,r,f);}void Modify(int v) { int a=p[v]; while(top[a]!=top[1]) { Modify(rt[v],rt[v],lx,rx,dfn[top[a]],dfn[a],1); a=fa[top[a]]; } Modify(rt[v],rt[v],lx,rx,dfn[1],dfn[a],1);}ll query(int v,int lx,int rx,int l,int r) { if(!v||lx>r||rx
>1; ans+=query(tr[v].ls,lx,mid,l,r)+query(tr[v].rs,mid+1,rx,l,r); return ans;}ll query(int rt,int a) { ll ans=0; while(top[a]!=top[1]) { ans+=query(rt,lx,rx,dfn[top[a]],dfn[a]); a=fa[top[a]]; } ans+=query(rt,lx,rx,dfn[1],dfn[a]); return ans;}void dfs3(int v) { rt[v]=rt[fa[v]]; Modify(v); for(int i=h[v];i;i=s[i].next) { int to=s[i].to; if(to==fa[v]) continue ; dfs3(to); }}int main() { type=Get(); n=Get(),m=Get(); int a,b,d; for(int i=1;i

转载于:https://www.cnblogs.com/hchhch233/p/10503205.html

你可能感兴趣的文章
Cas_个人理解
查看>>
UISearchController
查看>>
梦断代码阅读笔记02
查看>>
轮毂电机光电增量编码器的ABZ信号详解
查看>>
TextBox Template
查看>>
Linux MySQL 储存中文失败简单解决办法
查看>>
求最大值及其下标
查看>>
洛谷——P1330 封锁阳光大学
查看>>
css选择器
查看>>
zabbix-agent配置文件说明
查看>>
linux系统配置之bash shell的配置(centos)
查看>>
linux C 9*9
查看>>
hdu 1695: GCD 【莫比乌斯反演】
查看>>
python的string操作总结
查看>>
如何把word中的图片怎么导出来呢?
查看>>
Python连接Arduino的方法
查看>>
CMD指令大全
查看>>
十五天精通WCF——第二天 告别烦恼的config配置
查看>>
Qt多线程学习:创建多线程
查看>>
设计模式学习---UML常见关系的实现
查看>>