题目链接: http://poj.org/problem?id=2763

题意: 第一行输入 n, q, s 分别为树的顶点个数, 询问/修改个数, 初始位置. 接下来 n - 1 行形如 x, y, w 的输入为点 x, y 之间连边且边权为 w.

接下来 q 行输入, 若输入形式为 1 x y 则为将点 x 的权值修改为 y , 若输入形式为 0 x 则询问 s 到 x 的最短距离为多少. 上一组的 x 为下一组的 s.

思路: 若去掉修改边权部分, 则为一个 lca 模板题. 对于修改边权, 直接暴力向下修改 dis 数组可能会 tle . 可以将树映射到线段树上, 那样修改时间可降为为 log(n).

具体操作为, dfs 出每点的入点时间戳 l [MAXN] 和出点时间戳 r [MAXN] , 并记录 dfs 顺序 sol [MAXN] .

将 dis [sol [MAXN] ] 放入 sum 数组建线段树.

那么 x 到根结点的距离为: query(l[x], l[x], 1, n, 1) .

将 x 点的权值由 w 修改到 w' 操作为: updata(l[x], r[x], w - w', 1, n, 1) .

代码:

 #include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std; const int MAXN = 3e5 + ;
struct node{
int v, w, next;
node(){};
node(int V, int W, int NEXT) : v(V), w(W), next(NEXT){};
}edge[MAXN << ]; int dp[MAXN << ][];
int a[MAXN], b[MAXN], w[MAXN];
int sum[MAXN << ], add[MAXN << ];
int l[MAXN], r[MAXN], sol[MAXN], cnt;
int head[MAXN], dis[MAXN], dep[MAXN], ip, indx;
int first[MAXN], ver[MAXN << ], deep[MAXN << ]; void init(void){
memset(head, -, sizeof(head));
ip = ;
cnt = ;
indx = ;
} void addedge(int u, int v, int w){
edge[ip] = node(v, w, head[u]);
head[u] = ip++;
} void dfs(int u, int pre, int h){
dep[u] = h;
ver[++indx] = u;
deep[indx] = h;
first[u] = indx;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].v;
if(v == pre) continue;
dis[v] = dis[u] + edge[i].w;
dfs(v, u, h + );
ver[++indx] = u;
deep[indx] = h;
}
} void ST(int n){
for(int i = ; i <= n; i++){
dp[i][] = i;
}
for(int j = ; ( << j) <= n; j++){
for(int i = ; i + ( << j) - <= n; i++){
int x = dp[i][j - ], y = dp[i + ( << (j - ))][j - ];
dp[i][j] = deep[x] < deep[y] ? x : y;
}
}
} int RMQ(int l, int r){
int len = log2(r - l + );
int x = dp[l][len], y = dp[r - ( << len) + ][len];
return deep[x] < deep[y] ? x : y;
} int LCA(int x, int y){
int l = first[x], r = first[y];
if(l > r) swap(l, r);
int pos = RMQ(l, r);
return ver[pos];
} void dfs2(int x, int pre){
sol[++cnt] = x;
l[x] = cnt;
for(int i = head[x]; i != -; i = edge[i].next){
int v = edge[i].v;
if(v != pre) dfs2(v, x);
}
r[x] = cnt;
} void push_up(int rt){
sum[rt] = sum[rt << ] + sum[rt << | ];
} void push_down(int rt, int m){
if(add[rt]){
add[rt << ] += add[rt];
add[rt << | ] += add[rt];
sum[rt << ] += (m - (m >> )) * add[rt];
sum[rt << | ] += (m >> ) * add[rt];
add[rt] = ;
}
} void build(int l, int r, int rt){
add[rt] = ;
if(l == r){
sum[rt] = dis[sol[l]];
return;
}
int mid = (l + r) >> ;
build(lson);
build(rson);
push_up(rt);
} void updata(int L, int R, int key, int l, int r, int rt){
if(L <= l && R >= r){
sum[rt] += (r - l + ) * key;
add[rt] += key;
return;
}
push_down(rt, r - l + );
int mid = (l + r) >> ;
if(L <= mid) updata(L, R, key, lson);
if(R > mid) updata(L, R, key, rson);
push_up(rt);
} int query(int L, int R, int l, int r, int rt){
if(L <= l && R >= r) return sum[rt];
push_down(rt, r - l + );
int mid = (l + r) >> ;
int ans = ;
if(L <= mid) ans += query(L, R, lson);
if(R > mid) ans += query(L, R, rson);
return ans;
} int main(void){
int n, q, s, x, y, z, op;
while(~scanf("%d%d%d", &n, &q, &s)){
init();
for(int i = ; i < n; i++){
scanf("%d%d%d", &x, &y, &z);
addedge(x, y, z);
addedge(y, x, z);
a[i] = x;
b[i] = y;
w[i] = z;
}
dis[] = ;
dfs(, -, );
ST(indx);
dfs2(, -);
build(, cnt, );
while(q--){
scanf("%d", &op);
if(!op){
scanf("%d", &y);
int lca = LCA(s, y);
int sol1 = query(l[s], l[s], , cnt, );
int sol2 = query(l[y], l[y], , cnt, );
int sol3 = query(l[lca], l[lca], , cnt, );
printf("%d\n", sol1 + sol2 - * sol3);
s = y;
}else{
scanf("%d%d", &x, &y);
int u = a[x], v = b[x], add = y - w[x];
int cnt2 = dep[u] > dep[v] ? u : v;
updata(l[cnt2], r[cnt2], add, , cnt, );
w[x] = y;//注意记录修改后的权值
}
}
}
return ;
}

poj2763(lca / RMQ + 线段树)的更多相关文章

  1. NBU 2475 Survivors(RMQ线段树)

    NBU 2475Survivors 题目链接:http://acm.nbu.edu.cn/v1.0/Problems/Problem.php?pid=2475 题意:给定n个人,每个人有strengt ...

  2. Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)

    Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...

  3. lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增

    https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...

  4. UESTC 764 失落的圣诞节 --RMQ/线段树

    题意:n种物品,每种物品对不同的人都有不同的价值,有三个人选,第一个为普通学生,第二个是集,第三个是祈,集和祈可以选一样的,并且还会获得加分,集和祈选的普通学生都不能选,问三个人怎样选才能使总分最高. ...

  5. [RMQ] [线段树] POJ 3368 Frequent Values

    一句话,多次查询区间的众数的次数 注意多组数据!!!! RMQ方法: 预处理 i 及其之前相同的数的个数 再倒着预处理出 i 到不是与 a[i] 相等的位置之前的一个位置, 查询时分成相同的一段和不同 ...

  6. VJ16216/RMQ/线段树单点更新

    题目链接 /* 单点更新,用RMQ维护最大值,add对c[i]修改,或加,或减. 求[l,r]的和,用sum(r)-sum(l-1).即可. */ #include<cmath> #inc ...

  7. 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)

    题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...

  8. ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...

  9. CSU1553 Good subsequence —— 二分 + RMQ/线段树

    题目链接: http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1553 Description Give you a sequence of n n ...

随机推荐

  1. iis_rewrite3突然无法使用(因为它过期啦)

    转自http://www.b1y.cn/post/216.html ISAPI_Rewrite3完全版会有45天的试用期,过期了需要99美元进行够买,网上有很多破解版的,方法如下: 1.先从官网下一个 ...

  2. BEC listen and translation exercise 38

    很高兴看到有这么多人想了解我们的体育设施.It's good to see that there are so many people wanting to find out about our sp ...

  3. Android中的优化技巧

    高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操作都默认在主线程(UI线程)中进行的,这样App的响应速度就会受到影响.会导致程序陷入卡顿.死掉甚至会发生系统错误. 为 ...

  4. Exchange邮箱设置,android手机和mac book

    假设 用户名:abc 密码:123 公司名是:qq 一 android手机: 1 输入地址:abc@qq.com 2 密码:123 3 协议:EXCHANGE 点击下一步 用户名:abc 域名:qqc ...

  5. 使用Visual Studio进行单元测试-Part2

    写在开头:Coding ain't done until all the tests run. No unit test no BB. 另外有童鞋在上一篇博文留言说找不到Add Fake Assemb ...

  6. 开启现有android项目

    开启工程 在屏幕上方的选单列上,选择「File->New->Project」, 会弹出「New Project」对话视窗.Eclipse 是通用的编辑环境,可根据你所安装的不同扩充套件而支 ...

  7. java中的设计模式及其六大原则

    设计模式分类: 一共分为3大类:创造型模式.结构型模式.行为型模式. 创造型模式:工厂方法(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder). ...

  8. redhat 安装lamp

    安装Apache yum install httpd 安装MySql yum install mysql mysql-server 安装php yum install php 安装php的mysql模 ...

  9. Centos开启telnet/ssh/ftp/sftp服务

    Telnet 开启telnet服务步骤: 1.   查看CentOS/Telnet_server版本:#cat /etc/issue,   #rpm -qa | grep telnet 2.   安装 ...

  10. SharePoint Project Server List 列表CURD操作使用rest api接口

    //#region 界面交互代码 var issuesUtils = issuesUtils || {}; (function () { /** * 点击问题提处理方案按钮事件 */ issuesUt ...