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. Centos 7.6搭建LNMP环境的web服务器

    一.安装软件 1.1.MYSQL安装 下载mysql的repo源: wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rp ...

  2. 爬虫之re数据提取的使用

    本文将业务场景中最常用的几点实例,给大家列举出来,不常见的不再一一赘述.  使用urllib库可以模拟浏览器发送请求获得服务器返回的数据,下一步就是把有用的数据提取出来.数据分为两种形式:结构化和非结 ...

  3. mysql无法远程连接

    在mysql的mysql数据库下: select user,host from user;(查看,没有本机的访问权限) grant all privileges on *.* to root@&quo ...

  4. nginx比apache处理静态文件速度快,但是nginx处理大量并发的php请求时,容易出现502错误,频率大概是多少

    首先要明确一点的是502是怎么出现的,为什么会出现502呢? 一般而言,出现502的错误是因为php-cgi连接数不够导致的.举个例子:php-cgi开10个进程,前端发20个请求,每个请求的脚本都s ...

  5. jQuery效果之jQuery实现图片的依次加载图片

    css代码: ;;} ul#portfolio li{float: left;margin:0 5px 0 0;width:250px;height: 250px;list-style: none;} ...

  6. 洛谷P4065 [JXOI2017]颜色(线段树)

    题意 题目链接 Sol 线段树板子题都做不出来,真是越来越菜了.. 根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过. 所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这 ...

  7. Stable Fur Generation on Mesh

    After tested the Maya 2015 XGen Grooming, we dropped it, that's really slow and unstable, totally no ...

  8. hdu-2018题(母牛问题)

    HDU-2018题/*有一头母牛,它每年年初生一头小母牛.每头小母牛从第四个年头开始,每年年初也生一头小母牛.请编程实现在第n年的时候,共有多少头母牛?Input输入数据由多个测试实例组成,每个测试实 ...

  9. Flutter 布局(一)- Container详解

    本文主要介绍Flutter中非常常见的Container,列举了一些实际例子介绍如何使用. 1. 简介 A convenience widget that combines common painti ...

  10. 使用nginx代理后以及配置https后,如何获取真实的ip地址

    使用nginx代理后以及配置https后,如何获取真实的ip地址 Date:2018-8-27 14:15:51 使用nginx, apache等反向代理后,如果想获取请求的真实ip,要在nginx中 ...