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 ...
随机推荐
- iis_rewrite3突然无法使用(因为它过期啦)
转自http://www.b1y.cn/post/216.html ISAPI_Rewrite3完全版会有45天的试用期,过期了需要99美元进行够买,网上有很多破解版的,方法如下: 1.先从官网下一个 ...
- BEC listen and translation exercise 38
很高兴看到有这么多人想了解我们的体育设施.It's good to see that there are so many people wanting to find out about our sp ...
- Android中的优化技巧
高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操作都默认在主线程(UI线程)中进行的,这样App的响应速度就会受到影响.会导致程序陷入卡顿.死掉甚至会发生系统错误. 为 ...
- Exchange邮箱设置,android手机和mac book
假设 用户名:abc 密码:123 公司名是:qq 一 android手机: 1 输入地址:abc@qq.com 2 密码:123 3 协议:EXCHANGE 点击下一步 用户名:abc 域名:qqc ...
- 使用Visual Studio进行单元测试-Part2
写在开头:Coding ain't done until all the tests run. No unit test no BB. 另外有童鞋在上一篇博文留言说找不到Add Fake Assemb ...
- 开启现有android项目
开启工程 在屏幕上方的选单列上,选择「File->New->Project」, 会弹出「New Project」对话视窗.Eclipse 是通用的编辑环境,可根据你所安装的不同扩充套件而支 ...
- java中的设计模式及其六大原则
设计模式分类: 一共分为3大类:创造型模式.结构型模式.行为型模式. 创造型模式:工厂方法(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder). ...
- redhat 安装lamp
安装Apache yum install httpd 安装MySql yum install mysql mysql-server 安装php yum install php 安装php的mysql模 ...
- Centos开启telnet/ssh/ftp/sftp服务
Telnet 开启telnet服务步骤: 1. 查看CentOS/Telnet_server版本:#cat /etc/issue, #rpm -qa | grep telnet 2. 安装 ...
- SharePoint Project Server List 列表CURD操作使用rest api接口
//#region 界面交互代码 var issuesUtils = issuesUtils || {}; (function () { /** * 点击问题提处理方案按钮事件 */ issuesUt ...