这道题可以树链剖分做。但是最近在给学弟搞数据结构复习了LCA树状数组RMQ

然后就搞了一发LCA+树状数组维护。

dis数组维护当前点到根节点的权值和。则dis(u,v) = dis[u]+dis[v]-2*dis[lca(u,v)]

修改的时候,单点修改影响了该点所有儿子的dis,刚好可以用dfs序定位所有儿子,用树状数组改段求点很方便。

http://blog.csdn.net/q573290534/article/details/6664454 树状数组的三种求和(改点求段,改段求点,改段求段)

http://blog.csdn.net/qwe2434127/article/details/49819975 dfs序题目类型

http://www.cnblogs.com/longdouhzt/archive/2011/10/16/2214034.html LCA题目小节

 #include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = 2e5+; int N,Q,S;
//vector <int> G[maxn]; struct edge{
int to,next,w;
}e[*maxn]; int head[*maxn],tot;
void add_edge(int u,int v,int w)
{
e[tot].to = v;
e[tot].w = w;
e[tot].next = head[u];
head[u] = tot++; e[tot].to = u;
e[tot].w = w;
e[tot].next = head[v];
head[v] = tot++;
} int in[maxn],out[maxn],P[*maxn],fa[maxn][],dep[maxn],dis[maxn],cnt;
void dfs(int u,int _fa,int _dep,int _dis)
{
in[u] = ++cnt;
P[cnt] = u;
fa[u][] = _fa;
dis[u] = _dis;
dep[u] = _dep;
for(int i=head[u];~i;i=e[i].next)
{
int v = e[i].to;
if(v == _fa) continue;
dfs(v,u,_dep+,_dis+e[i].w);
}
out[u] = ++cnt;
}
void debug()
{
printf("in:\t");for(int i=;i<=N;i++) printf("%d ",in[i]);puts("");
printf("out:\t");for(int i=;i<=N;i++) printf("%d ",out[i]);puts("");
printf("p:\t");for(int i=;i<=cnt;i++) printf("%d ",P[i]);puts("");
printf("dis:\t");for(int i=;i<=N;i++) printf("%d ",dis[i]);puts("");
printf("dep:\t");for(int i=;i<=N;i++) printf("%d ",dep[i]);puts("");
printf("edge:");for(int i=;i<tot;i++) printf("\tto:%d w:%d\n",e[i].to,e[i].w);
} int initLCA()
{
int m = (int)log(N)/log()+;
for(int k=;k<m;k++)
{
for(int v=;v<=N;v++)
{
if(fa[v][k] < ) {fa[v][k+] = -;continue;}
else fa[v][k+] = fa[fa[v][k]][k];
}
}
} int LCA(int u,int v)
{
int m = (int)log(N)/log()+;
if(dep[v] > dep[u]) swap(u,v);
for(int k=;k<m;k++)
{
if((dep[u]-dep[v])>>k & )
u = fa[u][k];
}
if(u == v) return u;
for(int k=m-;k>=;k--)
{
if(fa[u][k] != fa[v][k])
{
u = fa[u][k];
v = fa[v][k];
}
}
return fa[u][];
} int c[*maxn];
int lowbit(int x) {return x&-x;} void init()
{
memset(head,-,sizeof head);
memset(fa,-,sizeof fa);
memset(c,,sizeof c);
memset(in,,sizeof in);
memset(out,,sizeof out);
tot = ;
cnt = ;
} void add(int x,int d)
{
while(x)
{
c[x] += d;
x -= lowbit(x);
}
}
void add_seg(int l,int r,int d)
{
add(r,d);
add(l-,-d);
}
int sum(int x)
{
int res = ;
//printf("u:%d ",P[x]);
while(x <= cnt)
{
res += c[x];
x += lowbit(x);
}
//printf("res:%d\n",res);
return res;
}
int dist(int x)
{
if(x == -) return ;
return sum(in[x]) + dis[x];
}
int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d%d%d",&N,&Q,&S))
{
init();
for(int i=,u,v,w;i<N-;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
dfs(,-,,);
//debug();
initLCA();
for(int i=;i<tot;i+=)
{
if(dep[e[i].to] < dep[e[i+].to]) swap(e[i].to,e[i+].to);
}
int op;
for(int i=,a,b,c;i<Q;i++)
{
scanf("%d",&op);
if(op == )
{
scanf("%d",&a);
int lca = LCA(S,a);
//printf("lca:%d\n",lca); printf("%d\n",dist(S)+dist(a)-*(dist(lca)));
S = a;
}else
{
scanf("%d%d",&a,&b);
a--;
int u = e[a*].to;
int dw = b - (dist(u) - dist(fa[u][]));
//printf("dw:%d u:%d\n",dw,u);
add_seg(in[u],out[u],dw);
}
}
}
}

POJ2763-Housewife Wind-树上单点修改区间求和的更多相关文章

  1. 【DFS序+单点修改区间求和】POJ 3321 Apple Tree

    poj.org/problem?id=3321 [题意] 给一棵n个节点的树,每个节点开始有一个苹果,m次操作 1.将某个结点的苹果数异或 1 2.查询一棵子树内的苹果数 #include<io ...

  2. Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

    Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't wa ...

  3. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  4. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  5. LightOJ 1112 Curious Robin Hood (单点更新+区间求和)

    http://lightoj.com/volume_showproblem.php?problem=1112 题目大意: 1 i        将第i个数值输出,并将第i个值清0 2 i v     ...

  6. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

  7. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  8. HDOJ(HDU).1166 敌兵布阵 (ST 单点更新 区间求和)

    HDOJ(HDU).1166 敌兵布阵 (ST 单点更新 区间求和) 点我挑战题目 题意分析 根据数据范围和询问次数的规模,应该不难看出是个数据结构题目,题目比较裸.题中包括以下命令: 1.Add(i ...

  9. hdu 1166线段树 单点更新 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

随机推荐

  1. ML.NET 示例:回归之价格预测

    写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...

  2. COMCMS 微进阶篇,从0开始部署到Centos 7.4

    言:上一篇,我们介绍了,如何本地调试和部署到windows服务器. 本篇,将带大家,从0到1,开始部署到Centos系统上... 经过测试,可以完美支持Centos.这也是.net core 跨平台的 ...

  3. jqGrid之treeGrid及行拖拽

    单纯的做个小记录 今天做功能用到了jqGrid里面的treeGrid,遇到几个问题,这里做下记录 treeGrid 树表格的应用在官网给出了很直白的例子: 1.http://blog.mn886.ne ...

  4. ASP.NET Core 企业开发架构概述

    企业开发框架包括垂直方向架构和水平方向架构.垂直方向架构是指一个应用程序的由下到上叠加多层的架构,同时这样的程序又叫整体式程序.水平方向架构是指将大应用分成若干小的应用实现系统功能的架构,同时这样的系 ...

  5. case when then的用法-leetcode交换工资

    case具有两种格式:简单case函数和case搜索函数. --简单case函数 case sex when ' then '男' when ' then '女’ else '其他' end --ca ...

  6. MySQL中myisam与innodb的区别

    1.  myisam与innodb的5点不同 1>.InnoDB支持事物,而MyISAM不支持事物 2>.InnoDB支持行级锁,而MyISAM支持表级锁 3>.InnoDB支持MV ...

  7. Python是如何进行内存管理

    三个方面:一对象的引用计数机制,二垃圾回收机制,三内存池机制 一.对象的引用计数机制 Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数. 引用计数增加的情况: 1,一个对象分 ...

  8. iOS使用XZMRefresh实现UITableView或UICollectionView横向刷新

    https://blog.csdn.net/u013285730/article/details/50615551?utm_source=blogxgwz6 XZMRefresh The easies ...

  9. 使用队列queue实现一个简单的生产者消费者模型

    一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...

  10. Vector源码分析

    Vector与ArrayList底层实现基本类似,底层都是用数组实现的,最大的不同是Vector是线程安全的.ArrayList源码分析请参考ArrayList源码分析 一.源码分析 基于jdk1.7 ...