POJ2763 Housewife Wind 树链剖分 边权

传送门:http://poj.org/problem?id=2763

题意:

n个点的,n-1条边,有边权

修改单边边权

询问 输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

题解:

树链剖分裸题

树链剖分就是将树分割为多条边,然后利用数据结构来维护这些链的一个技巧

  • 重儿子:父亲节点的所有儿子中子树结点数目最多( sizesiz**e 最大)的结点;
  • 轻儿子:父亲节点中除了重儿子以外的儿子;
  • 重边:父亲结点和重儿子连成的边;
  • 轻边:父亲节点和轻儿子连成的边;
  • 重链:由多条重边连接而成的路径;
  • 轻链:由多条轻边连接而成的路径;

1.求出子树大小和每个点的重儿子,处理sz数组,son数组,fa数组和dep数组

2.连接重链,记录dfs序,每个链的顶端节点,处理出rank数组,top数组,id数组

3.维护链上信息

修改边权就查询点的深度大的点,用大的点去存这条边的边权,其余的就和点权的是一样的了

代码:

#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f; int n, m, Q;
int a[maxn], sz[maxn], dep[maxn], fa[maxn], top[maxn], id[maxn], son[maxn], Rank[maxn];
int sum[maxn << 2], lazy[maxn << 2]; struct EDGE {
int u, v, nt;
} edge[maxn << 1];
int head[maxn], summ, cnt; void add_edge(int u, int v) {
edge[++summ].u = u; edge[summ].v = v; edge[summ].nt = head[u]; head[u] = summ;
} void dfs1(int u) {
sz[u] = 1; son[u] = 0;
for (int i = head[u]; ~i; i = edge[i].nt) {
int v = edge[i].v;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
} void dfs2(int u, int tp, int x) {
top[u] = tp; id[u] = ++cnt; Rank[cnt] = u;
if (son[u]) dfs2(son[u], tp, 1);
for (int i = head[u]; ~i; i = edge[i].nt) {
int v = edge[i].v;
if (v == son[u] || v == fa[u]) continue;
dfs2(v, v, 2);
}
} void init() {
memset(head, -1, sizeof(head));
summ = 1; cnt = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v); add_edge(v, u);
}
dep[1] = 1; fa[1] = 0;
dfs1(1);
dfs2(1, 1, 1);
} void pushup(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
} void pushdown(int rt, int mid) {
if (lazy[rt]) {
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
sum[rt << 1] += lazy[rt] * (mid - mid / 2);
sum[rt << 1 | 1] += lazy[rt] * (mid / 2);
lazy[rt] = 0;
}
} void build(int l, int r, int rt) {
lazy[rt] = 0;
if (l == r) {
sum[rt] = a[Rank[l]];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
} void update(int L, int R, int val, int l, int r, int rt) {
if (L <= l && r <= R) {
sum[rt] += val * (r - l + 1);
lazy[rt] += val;
return;
}
pushdown(rt, r - l + 1);
int mid = (l + r) >> 1;
if (L <= mid) update(L, R, val, lson);
if (mid < R) update(L, R, val, rson);
pushup(rt);
} int query(int pos, int l, int r, int rt) {
if (l == r) {
return sum[rt];
}
pushdown(rt, r - l + 1);
int mid = (l + r) >> 1;
if (pos <= mid) return query(pos, lson);
if (mid < pos) return query(pos, rson);
} void change(int x, int y, int val) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
update(id[top[x]], id[x], val, 1, n, 1);
x = fa[top[x]];
}
if (dep[x] > dep[y]) std::swap(x, y);
update(id[x], id[y], val, 1, n, 1);
} int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
while (~scanf("%d %d %d", &n, &m, &Q)) {
init();
build(1, n, 1);
while (Q--) {
char s[2];
int x, y, z;
scanf("%s", s);
if (s[0] == 'I') {
scanf("%d %d %d", &x, &y, &z);
change(x, y, z);
}
if (s[0] == 'D') {
scanf("%d %d %d", &x, &y, &z);
change(x, y, -z);
}
if (s[0] == 'Q') {
scanf("%d", &x);
printf("%d\n", query(id[x], 1, n, 1));
}
}
}
}

POJ2763 Housewife Wind 树链剖分 边权的更多相关文章

  1. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  2. POJ 2763 Housewife Wind (树链剖分 有修改单边权)

    题目链接:http://poj.org/problem?id=2763 n个节点的树上知道了每条边权,然后有两种操作:0操作是输出 当前节点到 x节点的最短距离,并移动到 x 节点位置:1操作是第i条 ...

  3. poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询

    /** problem: http://poj.org/problem?id=2763 **/ #include<stdio.h> #include<stdlib.h> #in ...

  4. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  5. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  6. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  7. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

  8. poj 2763 Housewife Wind(树链拆分)

    id=2763" target="_blank" style="">题目链接:poj 2763 Housewife Wind 题目大意:给定一棵 ...

  9. BZOJ 1984: 月下“毛景树” [树链剖分 边权]

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1728  Solved: 531[Submit][Status][Discu ...

随机推荐

  1. 【转】Sprague-Grundy函数

    http://www.cnitblog.com/weiweibbs/articles/42735.html 上一期的文章里我们仔细研究了Nim游戏,并且了解了找出必胜策略的方法.但如果把Nim的规则略 ...

  2. 轻松搞定word中让人抓狂的自动编号

    在word中使用自动编号时,如果一级编号是2,想让其后面的二级编号自动编号为2.1.2.2--,三级编号自动编号为2.1.1.2.1.2--:且在该一级编号调整为3时,后面的二级编号和三级编号的第一位 ...

  3. oracle中常用的时间格式转换

    1:取得当前日期是本月的第几周  select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; TO_CHAR(SYSDATE,'YY') se ...

  4. UVA_490:Rotating Sentences

    "R  Ie   n  te  h  iD  ne  kc  ,a   r  tt  he  es  r  eo  fn  oc  re  e   s  Ia   i  ad  m,  .  ...

  5. AbstractExecutorService的submit方法概要介绍

    1.概述 ExecutorService是JDK提供的框架,它简化了异步模式下的任务执行.一般来说,ExecutorService会自动提供一个线程池和API,用于为其分配任务. 2.实例化Execu ...

  6. oracle函数 NLS_INITCAP(x[,y])

    [功能]返回字符串并将字符串的第一个字母变为大写,其它字母小写; [参数]x字符型表达式 [参数]Nls_param可选, 查询数据级的NLS设置:select * from nls_database ...

  7. Android图形子系统

    图形操作可以有两种方式实现:一是利用通用CPU模拟图形操作:二是利用GPU专门做图形操作.前者会增加CPU的负担,在现在高分辨率已经是普遍现象的时候,让通用处理器来完成大量的图形计算已经不现实.And ...

  8. 学习HTML<audio>标签

    首先来看下这个例子: <audio controls autoplay="autoplay"> <source src="horse.ogg" ...

  9. H3C ARP

  10. [C#] 调试silverlight的时候,总是报“向占位程序传送了空的索引指针”

    这是由于visual studio在调试silverlight的时候,必须和ie一起工作. 按照以下步骤可以把ie设为visual studio的默认浏览器(不用修改操作系统的默认浏览器): 1) 在 ...