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

Description

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

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\) 满足:

有一篇写的很不错的博客

思路还是比较妙啊。

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

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

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

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

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 200005 using 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]]<size[to]) son[v]=to;
}
} int dfn[N],id;
void dfs2(int v,int tp) {
sum_dis[v]=sum_dis[fa[v]]+dis[p[v]];
dfn[v]=++id;
pre[dfn[v]]=dis[v]-dis[fa[v]];
top[v]=tp;
if(son[v]) dfs2(son[v],tp);
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(to==fa[v]||to==son[v]) continue ;
dfs2(to,to);
}
} int lca(int a,int b) {
while(top[a]!=top[b]) {
if(dep[top[a]]<dep[top[b]]) swap(a,b);
a=fa[top[a]];
}
return dep[a]<dep[b]?a:b;
} int tot;
int rt[N];
int lx,rx;
struct tree {
int ls,rs;
ll tag,sum;
}tr[N*150]; void Modify(int &v,int old,int lx,int rx,int l,int r,ll f) {
if(lx>r||rx<l) return ;
v=++tot;
tr[v]=tr[old];
if(l<=lx&&rx<=r) {
tr[v].tag+=f;
return ;
}
int L=max(lx,l),R=min(rx,r);
tr[v].sum+=f*(pre[R]-pre[L-1]);
int mid=lx+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<l) return 0;
if(l<=lx&&rx<=r) return tr[v].sum+tr[v].tag*(pre[rx]-pre[lx-1]);
ll ans=tr[v].tag*(pre[min(r,rx)]-pre[max(l,lx)-1]);
int mid=lx+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<n;i++) {
a=Get(),b=Get(),d=Get();
add(a,b,d),add(b,a,d);
}
for(int i=1;i<=n;i++) p[i]=Get();
lx=1,rx=n;
dfs(1);
dfs2(1,1);
for(int i=1;i<=n;i++) pre[i]+=pre[i-1];
dfs3(1); while(m--) {
ll x=Get()^(ans*type),y=Get()^(ans*type),k=Get()^(ans*type);
int f=lca(x,y);
ans=sum_dis[x]+sum_dis[y]-sum_dis[f]-sum_dis[fa[f]];
ans+=(dep[x]+dep[y]-2*dep[f]+1)*dis[k];
ans-=2*(query(rt[x],k)+query(rt[y],k)-query(rt[f],k)-query(rt[fa[f]],k));
cout<<ans<<"\n";
}
return 0;
}

Loj #6073.「2017 山东一轮集训 Day5」距离的更多相关文章

  1. loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

    题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...

  2. loj#6073. 「2017 山东一轮集训 Day5」距离(费用流)

    题意 题目链接 Sol 我们可以把图行列拆开,同时对于行/列拆成很多个联通块,然后考虑每个点所在的行联通块/列联通块的贡献. 可以这样建边 从S向每个行联通块连联通块大小条边,每条边的容量为1,费用为 ...

  3. 「2017 山东一轮集训 Day5」距离

    /* 写完开店再写这个题目顿时神清气爽, 腰也不疼了, 眼也不花了 首先考虑将询问拆开, 就是查询一些到根的链和点k的关系 根据我们开店的结论, 一个点集到一个定点的距离和可以分三部分算 那么就很简单 ...

  4. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  5. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  6. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

  7. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  8. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

  9. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

随机推荐

  1. T-SQL:qualify和window 使用(十七)

    1.qualify 是一个潜在的额外筛选器 主要用于对开窗函数的数据筛选 SELECT orderid, orderdate, val, RANK() OVER(ORDER BY val DESC) ...

  2. mybatis_07动态SQL_foreach循环

    废话不多说,直接上代码! <select id="findUserByforeach" parameterType="userQueryVO" resul ...

  3. Spring Security Oauth2 示例

    所有示例的依赖如下(均是SpringBoot项目) pom.xml <dependencies> <dependency> <groupId>org.springf ...

  4. JVM运行时数据区内容简述

    JVM运行时数据区分为五个部分:程序计数器.虚拟机栈.本地方法栈.堆.方法区.如下图所示,五部分其中又分为线程共享区域和线程私有区域,下面将分别介绍每一部分. 1. PC程序计数器 程序计数器是一块较 ...

  5. P3275 [SCOI2011]糖果

    题目描述 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配 ...

  6. JDCP连接池连接数据库报错:java.lang.AbstractMethodError: com.mysql.jdbc.Connection.isValid(I)Z

    完整报错是这样的: 小编的情况: 使用mysql的jar包版本: 使用的jdcp的相关jar包版本: 报错的原因: mysql的jar包版本过低. 更新到最新版mysql的jar包即可. 小编更新后的 ...

  7. mysql左连接

    举个例子说明: select d.id, d.uid,d.username,d.dateline, d.message,d.replynum, c.picid, c.filename from doi ...

  8. Vue的href动态拼接绑定

    <div id="appp"> <table> <tr v-for="item in sites"> <td> ...

  9. android adb 流程原理代码分析(一)

    由于要用到adb的知识,但是对adb啥也不了解,看了下android的代码,adb的源码在system/core/adb下面,然后网上搜下了资料,发现很多大神的源码分析,瞬间信心爆棚,把大神写的博客都 ...

  10. 乱码问题-页面跳转方式-Servlet配置文件

    1.HttpServletRequest a)HttpServletRequest是一个接口,继承了ServletRequest接口: b)HttpServletRequest对象由服务器创建,并作为 ...