poj2763(lca / RMQ + 线段树)
题目链接: 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 + 线段树)的更多相关文章
- NBU 2475 Survivors(RMQ线段树)
NBU 2475Survivors 题目链接:http://acm.nbu.edu.cn/v1.0/Problems/Problem.php?pid=2475 题意:给定n个人,每个人有strengt ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增
https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...
- UESTC 764 失落的圣诞节 --RMQ/线段树
题意:n种物品,每种物品对不同的人都有不同的价值,有三个人选,第一个为普通学生,第二个是集,第三个是祈,集和祈可以选一样的,并且还会获得加分,集和祈选的普通学生都不能选,问三个人怎样选才能使总分最高. ...
- [RMQ] [线段树] POJ 3368 Frequent Values
一句话,多次查询区间的众数的次数 注意多组数据!!!! RMQ方法: 预处理 i 及其之前相同的数的个数 再倒着预处理出 i 到不是与 a[i] 相等的位置之前的一个位置, 查询时分成相同的一段和不同 ...
- VJ16216/RMQ/线段树单点更新
题目链接 /* 单点更新,用RMQ维护最大值,add对c[i]修改,或加,或减. 求[l,r]的和,用sum(r)-sum(l-1).即可. */ #include<cmath> #inc ...
- 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)
题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...
- ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...
- CSU1553 Good subsequence —— 二分 + RMQ/线段树
题目链接: http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1553 Description Give you a sequence of n n ...
随机推荐
- JavaScript常用函数以及语法
$("#dwid").val(checkedVal.join(',')); .字符串(String) trim() //去掉空格 1.声明 var myString ...
- 单机版 JedisUtil({基本操作封装工具类})【二】
<!--集成的RedisJAR--> <!--引入jedis需的jar包--> <dependency> <groupId>redis.clients& ...
- PS 滤镜— —Marble 效果
clc; clear all; close all; addpath('E:\PhotoShop Algortihm\Image Processing\PS Algorithm'); I=imread ...
- 2017-2018-1 20179215《Linux内核原理与分析》第七周作业
一.实验部分:分析Linux内核创建一个新进程的过程. [第一部分] 根据要求完成第一部分,步骤如下: 1. 首先进入虚拟机,打开终端,这命令行依次敲入以下命令: cd LinuxKernel ...
- 1018 Public Bike Management (30)(30 分)
时间限制400 ms 内存限制65536 kB 代码长度限制16000 B There is a public bike service in Hangzhou City which provides ...
- GCC生成动态库
main.c #include <stdio.h> void hello(void); int main(int argc, char ** argv) { printf("Th ...
- win32 获取 HotKey 控件中的内容(HKM_GETHOTKEY)
windows给我们提供了一个对话框控件HotKey非常好用,在设置热键的时候用起来很爽,但是一直百度就是没找到在win32下怎样通过消息获取这个控件里面的内容,找到的都是用MFC封装好的控件类来操作 ...
- 九 fork/join CompletableFuture
1: Fork/join fork/join: fork是分叉的意思, join是合并的意思. Fork/Join框架:是JAVA7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务 ...
- 字符串(String)
字符串是由字符组成的数组,但在JavaScript中字符串是不可变的:可以访问字符串任意位置的文本,但是JavaScript并未提供修改已知字符串内容的方法. 常见功能: obj.length ...
- html文档树形结构图