注意这里都是把边放到线段树中,所以lca的时候,要注意如果top[x]==top[y] && x==y 的时候已经完成了。

仔细想想边和点的不同之处!!!

#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000007
#define mod 100000000
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = ;
struct node
{
int to;
int val;
int next;
}edge[MAXN*];
int a[MAXN][];
int fa[MAXN],pre[MAXN],ind,w[MAXN],top[MAXN],siz[MAXN],son[MAXN],deq[MAXN],cnt;//w[]表示它和他父亲的连线在线段树种的位置
int vis[MAXN],n,m,tree[MAXN<<];
void add(int x,int y,int z)
{
edge[ind].to = y;
edge[ind].val = z;
edge[ind].next = pre[x];
pre[x] = ind++;
}
void dfs1(int rt,int pa,int d)
{
vis[rt] = ;
siz[rt] = ;
son[rt] = -;
deq[rt] = d;
fa[rt] = pa;
for(int i = pre[rt]; i != -; i = edge[i].next){
int t = edge[i].to;
if(!vis[t]){
dfs1(t,rt,d+);
siz[rt] += siz[t];
if(siz[t] > siz[son[rt]]){
son[rt] = t;
}
}
}
}
void dfs2(int rt,int tp)
{
vis[rt] = ;
w[rt] = ++ cnt;
top[rt] = tp;
if(son[rt] != -){
dfs2(son[rt],tp);
}
for(int i = pre[rt]; i != -; i = edge[i].next){
int t = edge[i].to;
if(!vis[t] && t != son[rt]){
dfs2(t,t);
}
}
}
void pushup(int rt)
{
tree[rt] = tree[rt<<] + tree[rt<<|];
}
void updata(int p,int val,int l,int r,int rt)
{
if(l == r){
tree[rt] = val;
return ;
}
int m = (l + r) >> ;
if(m >= p){
updata(p,val,lson);
}
else {
updata(p,val,rson);
}
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R){
return tree[rt];
}
int m = (l + r) >> ;
int ans = ;
if(m >= L){
ans += query(L,R,lson);
}
if(m < R){
ans += query(L,R,rson);
}
return ans;
}
int lca(int x,int y)
{
int ans = ;
while(top[x] != top[y]){
if(deq[top[x]] < deq[top[y]]){
swap(x,y);
}
ans += query(w[top[x]],w[x],,cnt,);
x = fa[top[x]];
}
if(x == y){//同一点没有边,仔细想想这就是为什么边和点的不同地方!
return ans;
}
if(deq[x] < deq[y]){
swap(x,y);
} ans += query(w[son[y]],w[x],,cnt,);//既然top[x] == top[y]说明x 和 y在同一条重边上 所以son[y]也在该路径上
//并且是树根的孩子,又w[]表示该点和其父亲相连的点的边在线段树中的编号,
//所以需要这步,这样能得出答案。
return ans;
}
int main()
{
int s,p;
while(~scanf("%d%d%d",&n,&p,&s)){
int x,y,z;
ind = ;
memset(pre,-,sizeof(pre));
for(int i = ; i < n; i++){
scanf("%d%d%d",&a[i][],&a[i][],&a[i][]);
add(a[i][],a[i][],a[i][]);
add(a[i][],a[i][],a[i][]);
}
memset(vis,,sizeof(vis));
dfs1(,,);//求deq siz son fa cnt = ;
memset(vis,,sizeof(vis));
dfs2(,);//求top w
memset(tree,,sizeof(tree));
for(int i = ; i < n; i++){
if(deq[a[i][]] < deq[a[i][]]){//让a[i][0]在下面
swap(a[i][],a[i][]);
}
updata(w[a[i][]],a[i][],,cnt,);//将a[i][0]和他父亲相连的边插入到线段树中
}
int q;
while(p--){
scanf("%d",&q);
if(q == ){
scanf("%d",&x);
printf("%d\n",lca(s,x));
s = x;
}
else {
scanf("%d%d",&x,&y);
updata(w[a[x][]],y,,cnt,);
}
}
}
return ;
}

poj2763 树链剖分(线段树)的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. 如何利用ZBrush中的DynaMesh创建身体(二)

    之前的ZBrush教程我们在了解了人体比例和结构的前提下,使用ZBrush®软件中的Append功能和InsertSphere笔刷添加躯干.本讲将参照图片继续对“亡灵僵尸”的形体结构进行细致刻画和使用 ...

  2. 原创翻译-测试驱动开发(TDD)

    测试驱动开发原则 翻译自<<Expert Python Programming>> 测试驱动开发是指首先编写包含所有测试软件特点的测试集,然后再去开发软件.也就是说,在编写软件 ...

  3. ref out 方法参数

    ref out 相似 ref和out两个关键字的作用大致相同,但是有一些微妙但是重要的区别. 两者的行为相似到连编译器都认为这两者不能被重载:public void SampleMethod(out ...

  4. VS 扩展推荐

    Visual Studio 工欲善其事,必先利器.本着这样的观念,对于经常使用的工具,我喜欢去研究研究,帮助我提高效率. Visual Studio Microsoft Visual Studio(简 ...

  5. Hill密码

    希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=, B=, C=... 一串字母当成n维向量,跟一个 ...

  6. c# 扩展方法奇思妙用

    # 扩展方法出来已久,介绍扩展方法的文章也很多,但都是笼统的.本人最近一直在思考扩展方法的应用,也悟出了一些,准备将这最近一段时间对扩展方法的思考,写成一个系列文章.每个文章只介绍一个应用方面,篇幅不 ...

  7. JavaScript Number 对象 Javascript Array对象 Location 对象方法 String对象方法

    JavaScript Number 对象 Number 对象属性 属性 描述 constructor 返回对创建此对象的 Number 函数的引用. MAX_VALUE 可表示的最大的数. MIN_V ...

  8. 25Mybatis_查询缓存的基本知识

    mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 一级和二级缓存的示意图:

  9. usb驱动开发2之代码地图

    USB只是Linux庞大家族里的一个小部落,host controller是它们的族长,族里的每个USB设备都需要被系统识别.下图显示包含一个USB接口的USB鼠标导出的结果. USB系统中的第一个U ...

  10. Silverlight 利用DataGrid行加载事件动态控制行列显示

    datagrid的绑定很好用,但有时候我们往往需要根据model内容来动态控制行或者列,该怎么办呢? 这时候,我们就需要用到行加载事件:在加载每一行数据的时候,根据数据的内容来控制相应的表格显示. 比 ...