题面

n点2n-2条有向边,数据先给一颗1为根的生成树边集,边目录按两部分给出

1、 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点 到达。

2、 接下来的 N-1 条边,一定是从 i 到 1(2<=i<=N)的有向边,保证每个点都能到

然后给出除1外每个点到1的距离,q次询问两个操作:

1 x w将第x条边的边权修改为w

2 u v问u v最短距离

【输入格式】 第一行是 2 个整数 N,Q,表示一共 N 个点 Q 次询问 接下来是 N-1 行,每行 3 个整数 U,V,W,表示了前 N-1 条边,u 到 v 的有向边 接下来 N-1 行,每行 3 个整数 U,V,W,描述了每个点到 1 号点的边,V==1 接下来是 Q 行,表示 Q 次修改与询问

【输出格式】 若干行,每行回答一次询问

20%数据 没有修改 30%数据 2<=N,Q<=1000 (其中有 10%数据没有修改) 100%数据 2<=N,Q<=100 000, 1 <=边权 <= 1000,000

分析

首先注意到了20%无修改,第一反应就想到了lca,因为lca的一大用处就是求树上两点距离

但是存在一个问题,这不是一棵普通的树,根据题意,有两种边,前n-1条边我们称为树边,后n-1条边我们称为返祖边

无修改的情况下,如果u是v的祖先,那就是纯lca模板了,关键在于如果u不是v祖先呢?那u要通过返祖边回到根节点,再从根节点走到v。但注意,u不仅可以从自身的返祖边回去,还可以从子树的返祖边回去,所以在lca时需初始化出以u回到1节点的最小代价(即对于去到整个子树每个节点的路径以及返祖的边综合起来求最小)。再加上30%的1000的数据(遍历子树的每个点修改),暴力轻松得40分

—————————————————————以下为正解——————————————————————————

首先我们在暴力的时候就考虑到了进行预处理从任意节点回根的最小代价,但现在我们必须要修改了,所以还要考虑从根到此节点的路径权值和。

定义dis[u]为从1->u->1的路径值。把返祖边记为rev[u],则1到u的树上距离为dis[u]-rev[u]

查询

则有两种情况:1.u还是v的祖先,则答案是(dis[v]-rev[v])-(dis[u]-rev[u])  //两树边相减

2.u不是v的祖先。需要在u的子树中找出最小的dis[k]值,则答案是dis[k]-(dis[u]-rev[u])+(dis[v]-rev[v])  //u返祖路径的值+从根到v的树边的值

根据上述思路,我们可以试着分两类边修改。

如果是任意节点u的树边,修改会影响到整棵子树的dis[],但是如果是返祖边只会影响u自己的dis[]。

思路大概告一段落

但在查询和修改过程中发现了一系列问题:1、需要维护子树的最小值。2、需要修改子树的dis.

所以用线段树维护dis,并通过dfs序编号(dfs序中一棵子树的节点是连续的,便于操作)。用st[u]记录以u为根的子树的开始的dfs序,ed[u]为结束的节点dfs序

#include<bits/stdc++.h>
using namespace std;
#define N 200000
#define INF 0x7fffffff
#define ll long long
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (t[p].l+t[p].r>>1)
ll first[N],dep[N],dfn[N],st[N],ed[N],dis[N],rev[N],ux[N],vx[N],wx[N];
ll fa[N][20];
ll n,q,cnt,idx;
struct email
{ll u,v;ll w;ll nxt;
}e[N*2];
struct NSD
{ll l,r;ll minx,lazy;
}t[N*4];inline void pushnow(ll p,ll val)
{t[p].lazy+=val;t[p].minx+=val;
}inline void pushup(ll p)
{t[p].minx=min(t[lc].minx,t[rc].minx);
}inline void pushdown(ll p)
{if(t[p].lazy){pushnow(lc,t[p].lazy);pushnow(rc,t[p].lazy);t[p].lazy=0;}
}void build(ll p,ll l,ll r)
{t[p].l=l;t[p].r=r;if(l==r){t[p].minx=dis[l];t[p].lazy=0;return;}build(lc,l,mid);build(rc,mid+1,r);pushup(p);
}void update(ll p,ll ql,ll qr,ll val)
{if(ql<=t[p].l&&t[p].r<=qr){pushnow(p,val);return ;}pushdown(p);if(ql<=mid)update(lc,ql,qr,val);if(qr>mid)update(rc,ql,qr,val);pushup(p);
}ll query(ll p,ll ql,ll qr)
{ll ans=INF;if(ql<=t[p].l&&t[p].r<=qr)return t[p].minx;pushdown(p);if(ql<=mid)ans=min(ans,query(lc,ql,qr));if(qr>mid)ans=min(ans,query(rc,ql,qr));pushup(p);return ans;
}inline void add(ll u,ll v,ll w)
{e[++cnt].nxt=first[u];first[u]=cnt;e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
}void dfs(ll u,ll f)
{for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];for(int i=first[u];i;i=e[i].nxt){int v=e[i].v;if(v==f)continue;dep[v]=dep[u]+1;fa[v][0]=u;dfs(v,u);}
}ll lca(ll x,ll y)
{if(dep[x]<dep[y])swap(x,y);ll t=dep[x]-dep[y];for(int i=0;(1<<i)<=t;i++)    if(t&(1<<i))x=fa[x][i];if(x==y)return x;for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}return fa[x][0];
}void getdfn(ll u,ll f,ll w)
{st[u]=++idx;dis[st[u]]=w+rev[u];for(int i=first[u];i;i=e[i].nxt){int v=e[i].v;if(v==f)continue;getdfn(v,u,w+e[i].w);}ed[u]=idx;
}int main()
{scanf("%lld%lld",&n,&q);for(int i=1;i<=(n-1)*2;i++){ll u,v,w;scanf("%lld%lld%lld",&u,&v,&w);ux[i]=u;vx[i]=v;wx[i]=w;if(i<n){add(u,v,w);add(v,u,w);}else    rev[u]=w;}getdfn(1,0,0);dfs(1,0);build(1,1,n);for(ll i=1;i<=q;i++){ll x;scanf("%lld",&x);if(x==1){ll k,w;scanf("%lld%lld",&k,&w);if(k>=n){update(1,st[ux[k]],st[ux[k]],w-rev[ux[k]]);rev[ux[k]]=w;}else{update(1,st[vx[k]],ed[vx[k]],w-wx[k]);wx[k]=w;}}else{ll u,v;scanf("%lld%lld",&u,&v);if(lca(u,v)==u){ll du=query(1,st[u],st[u])-rev[u];ll dv=query(1,st[v],st[v])-rev[v];printf("%lld\n",dv-du);}else{ll du=query(1,st[u],ed[u])-query(1,st[u],st[u])+rev[u];ll dv=query(1,st[v],st[v])-rev[v];printf("%lld\n",du+dv);}    }}    return 0;
}

转载于:https://www.cnblogs.com/NSD-email0820/p/9446553.html

【NOIP模拟】图论题Graph相关推荐

  1. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

  2. 闵梓轩大佬のnoip模拟题D1 总结 2017/10/26

    背景 题目概括 T1 题面 分析 90分算法 满分算法 T2 题面 分析 部分分算法 满分算法 满分代码 T3 题面 分析 代码 总结 背景 这道题目是去年的金牌大佬闵梓轩在一年前出的一套noip模拟 ...

  3. jyzy noip模拟赛5.22-2

    不知道哪来的题 jyzy noip模拟赛5.22-2 样例输入 1 2 3 4 样例输出 0.200000000000000 数据 |a|,|b|,|c|,|d|<=1e9 很多大佬迅速想到二分 ...

  4. HTTP协议漫谈 C#实现图(Graph) C#实现二叉查找树 浅谈进程同步和互斥的概念 C#实现平衡多路查找树(B树)...

    HTTP协议漫谈 简介 园子里已经有不少介绍HTTP的的好文章.对HTTP的一些细节介绍的比较好,所以本篇文章不会对HTTP的细节进行深究,而是从够高和更结构化的角度将HTTP协议的元素进行分类讲解. ...

  5. Noip 模拟练习5

    Noip 模拟练习5 满分300,本人240.修正后300. 难度中等. 太空密码 Description 人类一直致力于探索地外文明,为此科学家们建造了一个巨大的射电望远镜 用于接收宇宙射线.一天从 ...

  6. TVM 图优化Graph Optimization

    TVM 图优化Graph Optimization Codegen

  7. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  8. 十五、图(graph)

    引入 社交网络,如何存储微博.微信等这些社交网络的好友关系? ==>图 一.图(Graph)的相关概念 图:复杂的非线性表结构: 顶点(vertex):图中的元素: 边(edge):图中一个顶点 ...

  9. 数据结构与算法(C++)– 图(Graph)

    数据结构与算法(C++)– 图(Graph) 1.图的基础概念 定义:一个图G=(V, E)由顶点(vertex)的集V和边(edge)的集E组成. 边(edge):一对点即为一条边(v, w),其中 ...

最新文章

  1. Druid连接池一个设置引发的血案
  2. 多返回值函数的编写方法
  3. UIButton 按钮控件-IOS开发 (实例)
  4. 《拆弹专家2》观后感
  5. 9适应之力加多少攻击_剑盾铠之孤岛DLC新增内容大全! 宝可梦史上第一款DLC到底香不香(含试玩视频)...
  6. python参数类型_Python 参数类型和参数匹配模型
  7. 未知的生成错误 因为没有预加载,所以无法解析程序集 GalaSoft.MvvmLight
  8. 如何规范 CSS 的命名和书写
  9. 真格量化——中性策略交易期权
  10. java----IO和NIO的区别
  11. Android 对话框用法
  12. [Postgres] Group and Aggregate Data in Postgres
  13. 安装firefox扩展(xpi)文件的简便方法
  14. 微软补丁日安全公告|11月份
  15. 小程序开发视频教程免费下载
  16. 使用xshell上传文件
  17. android 投屏,华为手机的电脑模式是如何实现的
  18. 20sccm_SCCM安装及配置过程总结
  19. Nat Methods | 德州大学西南医学中心王涛/王莉等开发空间转录组数据降噪的新方法...
  20. 用python实现数度游戏

热门文章

  1. 函数,游标与存储过程的综合应用
  2. java的三大特性,封装,继承,多态
  3. linux命令学习-4-lsof
  4. 手摸手,带你用vue撸后台 系列一(基础篇) - 掘金
  5. Spring--Context
  6. 什么是高并发,如何避免高并发
  7. Spring Cloud Gateway 路由转发之After(Before)路由断言工厂使用
  8. 【C++STL/红黑树】POJ 3481 DoubleQueue
  9. Swoole 源码分析——Server模块之初始化
  10. Qualcomm QXDM工具简介和log抓取