树剖一好题。我心水了ww

题目描述
给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 输入输出格式
输入格式:
第一行输入一个n,表示节点个数 第二行到第n行每行输入三个数,ui,vi,wi,分别表示 ui,vi有一条边,边权是wi 第n+1行开始,一共有不定数量行,每一行分别有以下三种可能 CHANGE,QUERY同题意所述 DONE表示输入结束 输出格式:
对于每个QUERY操作,输出一个数,表示a b之间边权最大值

树链剖分维护。若对应的一组父亲节点\(x\)与子节点\(y\)之间有一条边,则将边权存为\(y\)点的点权。在dfs2内特殊处理即可。

对于修改,线段树动态维护一下最大值。

查询路径最大值按照常规树剖的跳链写法就可以了。由于是边权存为点权,不能计算最近公共祖先。\(LCA\)所代表的那条边并不在路径上qwq

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define MAXN 102333
using namespace std;
int h[MAXN],tot=0,cnt=0;
int n,m;
struct qwq
{
int nex,to,w;
int id;
}e[MAXN<<1];
int ans[MAXN<<2];
int w1[MAXN];
int dep[MAXN],son[MAXN]={},fa[MAXN],top[MAXN],siz[MAXN],id[MAXN]; inline void add(int x,int y,int w,int i)
{
e[++tot].to=y;
e[tot].nex=h[x];
e[tot].w=w;
e[tot].id=i;
h[x]=tot;
}
#define leftson cur<<1
#define rightson cur<<1|1
#define mid ((l+r)>>1)
#define push_up ans[cur]=max(ans[leftson],ans[rightson])
inline void build(int cur,int l,int r)
{
if (l==r)
{
ans[cur]=w1[l];
return;
}
build(leftson,l,mid);
build(rightson,mid+1,r);
push_up;
}
int tag[MAXN<<2];
#define push_down lazyadd(leftson,tag[cur]); lazyadd(rightson,tag[cur]); tag[cur]=0
inline void lazyadd(int cur,int del)
{
if (!del) return;
ans[cur]+=del;
tag[cur]+=del;
}
void change(int adl,int adr,int cur,int l,int r,int del)
{
if (adl<=l&&r<=adr)
{
ans[cur]=del;
tag[cur]=del;
return;
}
push_down;
if (adl<=mid) change(adl,adr,leftson,l,mid,del);
if (adl>mid) change(adl,adr,rightson,mid+1,r,del);
push_up;
}
int query(int ql,int qr,int cur,int l,int r)
{
if (ql<=l&&r<=qr)
{
return ans[cur];
}
int answ=-23333;
push_down;
if (ql<=mid) answ=max(answ,query(ql,qr,leftson,l,mid));
if (qr>mid) answ=max(answ,query(ql,qr,rightson,mid+1,r));
return answ;
} int segid[MAXN];
void dfs_fir(int x,int f,int dept)
{
fa[x]=f;
dep[x]=dept;
siz[x]=1;
int maxn=-1;
for (int i=h[x],y;i;i=e[i].nex)
{
y=e[i].to;
if (y==f) continue;
dfs_fir(y,x,dept+1);
siz[x]+=siz[y];
if (siz[y]>maxn)
{
son[x]=y;
maxn=siz[y];
}
}
}
void dfs_sec(int x,int ft,int w)
{
top[x]=ft;
id[x]=++cnt;
w1[cnt]=w;
if (!son[x]) return;
dfs_sec(son[x],ft,0);
for (int i=h[x],y;i;i=e[i].nex)
{
y=e[i].to;
if (y==fa[x]) continue;
if (y==son[x])
{
w1[id[son[x]]]=e[i].w;
segid[e[i].id]=id[son[x]];
continue;
}
dfs_sec(y,y,e[i].w);
segid[e[i].id]=id[y];
}
}
inline int query_(int x,int y)
{
int answer=-23333;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
answer=max(answer,query(id[top[x]],id[x],1,1,n));
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
answer=max(answer,query(id[x]+1,id[y],1,1,n));
return answer;
} int main()
{
scanf("%d",&n);
int x,y,w;
for (int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w,i);
add(y,x,w,i);
}
dfs_fir(1,1,1);
dfs_sec(1,1,0);
build(1,1,n);
string s="QWQ";
// for (int i=1;i<=n;i++)
// {
// printf("%d ",w1[id[i]]);
// }
// printf("\n\n");
while (s[0]!='D')
{
cin>>s;
if (s[0]=='D') continue;
scanf("%d%d",&x,&y);
if (s[0]=='Q')
{
if (x==y)
{
printf("0\n");
continue;
}
printf("%d\n",query_(x,y));
continue;
}
change(segid[x],segid[x],1,1,n,y);
}
return 0;
}

Luogu P4114 Qtree1的更多相关文章

  1. 【luogu P4114 Qtree1】 题解

    题目链接:https://www.luogu.org/problemnew/show/P4114 1.把边权转化到点权:选取连接这条边的两个点中较深的一个. 2.查询点到点之间的边权时,要从seg[x ...

  2. 洛谷 P4114 Qtree1 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...

  3. 洛谷 - P4114 - Qtree1 - 重链剖分

    https://www.luogu.org/problem/P4114 维护边权的话,用深度大的点表示这条边(可以遍历一边边询问两端深度,这样不需要修改dfs1,也可以在dfs1的时候向下走的同时把边 ...

  4. P4114 Qtree1

    思路 树剖一发,注意对LCA的处理 代码 #include <cstdio> #include <algorithm> #include <cstring> usi ...

  5. 洛谷 P4114 Qtree1

    Qtree系列都跟树有着莫大的联系,这道题当然也不例外 我是题面 读完题,我们大概就知道了,这道题非常简单,可以说是模板题.树剖+线段树轻松解决 直接看代码吧 #include<algorith ...

  6. 洛谷P4114 Qtree1

    题目描述 给定一棵\(n\)个节点的树,有两个操作: \(CHANGE\) \(i\) \(t_i\) 把第\(i\)条边的边权变成\(t_i\) \(QUERY\) \(a\) \(b\) 输出从\ ...

  7. 洛谷P4114 Qtree1(树链剖分+线段树)

    传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 //minamoto #include& ...

  8. 树链剖分好(du)题(liu)选做

    1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...

  9. 树链剖分【洛谷P4114】 Qtree1

    P4114 Qtree1 题目描述 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 码 ...

  10. 洛谷 P1505 [国家集训队]旅游 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ...

随机推荐

  1. Linux_MySQL

    MySQL 安装 AB复制 安装 1.编译安装 2.yum安装 [https://www.mysql.com/] yum安装的方式 1.在官网下载mysql rpm包 # wget https://d ...

  2. Vue二级联动上传图片

    二级联动的后台和之前一样都需要一个字典字段查询来实现二级联动 但是由于VUE语法和AJAX的不同在前台绑定的时候也有所不同 2.1 首先下拉框的写法就有了本质的改变通过v-model="&q ...

  3. localtime函数

    localtime函数: 将时间数值变换成本地时间,考虑到本地时区和夏令时标志; 原型: struct tm *localtime(const time_t * calptr); 头文件 <ti ...

  4. java15配置环境后java_version无反应(不显示“不是内部或外部命令”)

    重新装了jdk15来使用eclipse 配置完环境变量之后打开cmd输入 java -version 好家伙,居然一点反映都没有, 然后傻乎乎的跑回去重新配置JAVA_HOME和path 还是没用,细 ...

  5. 【Unity】阅读LuaFramework_UGUI的一种方法

    写在前面 我第一次接触到LuaFramework_UGUI是在一个工作项目中,当时也是第一次知道toLua.但我刚开始了解LuaFramework_UGUI时十分混乱,甚至将LuaFramework_ ...

  6. C语言转义序列

    转义序列 含义 \a 报警(ANSIC) \b 退格 \f 换页 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \\ 反斜杆\ \' 单引号 \" 双引号 \? 问号 \0oo ...

  7. C#中字符数组,字节数组和string之间的转化(转)

    原文链接:http://hi.baidu.com/endyli/item/7bf074945de35e1f934f41fe 来源: NDC(NetworkDiskClient)的界面和后台程序之间用S ...

  8. DASCTF NOV X联合出题人-PWN

    太忙了,下午4点才开始做,,剩下的以后补上 签个到 逻辑很简单两个功能的堆,一个就是申请heap.还有一个是检验如果校验通过就会得到flag 申请模块 ​ 中间0x886是个很恶心的东西,需要我们绕过 ...

  9. SQL 抽象语法树及改写场景应用

    SQL 抽象语法树及改写场景应用 1 背景 我们平时会写各种各样或简单或复杂的 sql 语句,提交后就会得到我们想要的结果集.比如 sql 语句,"select * from t_user ...

  10. windows tips

    u启动经典dos工具实现硬盘分区教程 https://jingyan.baidu.com/article/a3f121e4dbe55afc9052bbfe.html?st=2&net_type ...