树链剖分学习

https://blog.csdn.net/u013368721/article/details/39734871

https://www.cnblogs.com/George1994/p/7821357.html

核心:节点u的轻儿子为v   轻儿子的性质:size[v] <= size[u] / 2

故:每走一条轻链,节点数减少一半

又因:两个节点之间的路径,必为重链和轻边交替

故:从根结点到树上任意点经过的轻边以及重链都不会超过logn条

http://acm.hust.edu.cn/vjudge/problem/13013

树链剖分模版题

题意:

有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个权值,要求模拟两种操作:

1:QUERY x y 求节点x和节点y之间的路径中权值最大的边。

2:CHANGE p k修改第p条边的权值为k。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N=;
char s[];
struct trnode{
int lc,rc,l,r,c;
}t[*N];
struct node{
int x,y,d,next;
}a[*N],b[N];
int n,tl,z,len;
int first[N],tot[N],son[N],fa[N],dep[N],ys[N],top[N]; int maxx(int x,int y){return x>y ? x:y;} void ins(int x,int y,int d)
{
len++;
a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=first[x];first[x]=len;
} int build_tree(int l,int r)
{
int x=++tl;
t[x].l=l;t[x].r=r;t[x].c=;
t[x].lc=t[x].rc=-;
if(l<r)
{
int mid=(l+r)>>;
t[x].lc=build_tree(l,mid);
t[x].rc=build_tree(mid+,r);
}
return x;
} void change(int x,int p,int c)
{
if(t[x].l==t[x].r) {t[x].c=c;return;}
int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>;
if(p<=mid) change(lc,p,c);
else change(rc,p,c);
t[x].c=maxx(t[lc].c,t[rc].c);
} int query(int x,int l,int r)
{
if(t[x].l==l && t[x].r==r) return t[x].c;
int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>;
if(r<=mid) return query(lc,l,r);
else if(l>mid) return query(rc,l,r);
return maxx(query(lc,l,mid),query(rc,mid+,r));
} void dfs1(int x)
{
tot[x]=;son[x]=;
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa[x]) continue;
fa[y]=x;
dep[y]=dep[x]+;
dfs1(y);
if(tot[son[x]]<tot[y]) son[x]=y;
tot[x]+=tot[y];
}
} void dfs2(int x,int tp)
{
ys[x]=++z;top[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa[x] || y==son[x]) continue;
dfs2(y,y);
}
} int solve(int x,int y)
{
int tx=top[x],ty=top[y],ans=;
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(tx,ty),swap(x,y);//debug swap(x,y)之前漏了
ans=maxx(ans,query(,ys[ty],ys[y]));
y=fa[ty];ty=top[y];
}
if(x==y) return ans;
else
{
if(dep[x]>dep[y]) swap(x,y);
return maxx(ans,query(,ys[son[x]],ys[y]));
}
} int main()
{
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
len=;tl=;z=;dep[]=;tot[]=;
memset(fa,,sizeof(fa));
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].d);
ins(b[i].x,b[i].y,b[i].d);
ins(b[i].y,b[i].x,b[i].d);
}
dfs1();
dfs2(,);
build_tree(,z);
for(int i=;i<n;i++) if(dep[b[i].x]>dep[b[i].y]) swap(b[i].x,b[i].y);
for(int i=;i<n;i++) change(,ys[b[i].y],b[i].d);
while()
{
scanf("%s",s);
int x,y,d;
if(s[]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",solve(x,y));
}
if(s[]=='C')
{
scanf("%d%d",&x,&d);
change(,ys[b[x].y],d);
}
if(s[]=='D') break;
}
}
return ;
}

【SPOJ-QTREE】树链剖分的更多相关文章

  1. SPOJ QTREE 树链剖分

    树链剖分的第一题,易懂,注意这里是边. #include<queue> #include<stack> #include<cmath> #include<cs ...

  2. Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  3. 【学术篇】SPOJ QTREE 树链剖分

    发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...

  4. QTREE 树链剖分---模板 spoj QTREE

    <树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...

  5. SPOJ 375 树链剖分 QTREE - Query on a tree

    人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...

  6. SPOJ 375 树链剖分

    SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...

  7. SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I 给你一棵有边权的树,有两个操作:一个操作是输出l到 ...

  8. SPOJ 375 (树链剖分+线段树)

    题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...

  9. SPOJ375.QTREE树链剖分

    题意:一个树,a b c 代表a--b边的权值为c.CHANGE x y  把输入的第x条边的权值改为y,QUERY x y 查询x--y路径上边的权值的最大值. 第一次写树链剖分,其实树链剖分只能说 ...

  10. spoj 375 树链剖分 模板

    QTREE - Query on a tree #tree You are given a tree (an acyclic undirected connected graph) with N no ...

随机推荐

  1. 面试官常问的10个Linux问题

    1.如何暂停一个正在运行的进程,把其放在后台(不运行)? 为了停止正在运行的进程,让其再后台运行,我们可以使用组合键Ctrl+Z. 2.什么是安装Linux所需的最小分区数量,以及如何查看系统启动信息 ...

  2. Office使用技巧(不断补充)

    1.word中,第一行后面有很多空格,但把第二行的退到第一行来就删了第一行的字,为什么? 解决办法:应该是下一行开头部分是一个不可拆分的整体,上一行末尾放不下,只能放在下一行.处理方法:格式--段落- ...

  3. python内置模块[sys,os,os.path,stat]

    python内置模块[sys,os,os.path,stat] 内置模块是python自带功能,在使用内置模块时,需要遵循 先导入在 使用 一.sys 对象 描述 sys.argv 命令行参数获取,返 ...

  4. 【面试题】2018年最全Java面试通关秘籍第五套!

    [面试题]2018年最全Java面试通关秘籍第五套! 原创 2018-04-26 徐刘根 Java后端技术 第一套:<2018年最全Java面试通关秘籍第一套!> 第二套:<2018 ...

  5. Linux-Shell脚本编程-学习-8-函数

    在这章往后的学习中,我讲尽可能详细的讲书中讲到的都记录到这里,以便以后方便查看. 什么是函数,函数就是一段代码,这段代码可以在我们需要的位置调用,那么这段代码就叫做函数. 在Shell中,定义一个函数 ...

  6. Struts2(七.删除和修改用户功能的实现)

    一.删除功能 之前跳转用户列表的时候把用户id,用户名,用户密码存入了ActionContext 1.userlist.jsp <%@ page language="java" ...

  7. Spring实战第四章学习笔记————面向切面的Spring

    Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...

  8. NO6——KMP

    int next[N]; char str1[M],str2[N]; //str1 长,str2 短 //len1,len2,对应str1,str2的长 void get_next(int len2) ...

  9. JavaSE复习(五)网络编程

    客户端:java.net.Socket 类表示.创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信 服务端:java.net.ServerSocket 类表示.创建Ser ...

  10. webmagic 二次开发爬虫 爬取网站图片

    webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. webmagic介绍 编写一个简单的爬虫 webmagic的使用文档:http://w ...