您的位置:首页 > 其它

[HDU] 3966 树状数组+启发式树链剖分

2017-09-30 22:30 274 查看
树状数组+启发式树链剖分

一个讲解ppt

https://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html

例题:Aragorn’s Story

点权树+路经加减+单点询问

时间复杂度 O(n+n+nlogn+Qlogn)

空间复杂度 O(n)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = (int)5e5 + 5;
struct Edge{int to, next;} E[MAXN<<1];
int head[MAXN], tot;
int top[MAXN];//top[v] 表示v所在的重链的顶端节点
int fa[MAXN];//父亲节点
int deep[MAXN];//深度
int num[MAXN];//num[v] 表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v对应的位置
int fp[MAXN];//fp和p数组相反
int son[MAXN];//重儿子
int pos;
int N, M, P;

void add_edge(int u, int v) {
E[tot].to = v;
E[tot].next = head[u];
head[u] = tot++;
}

void dfs_1(int u, int u_fa, int u_deep) {
deep[u] = u_deep;
fa[u] = u_fa;
num[u] = 1;
for(int i = head[u]; ~i; i = E[i].next) {
int &v = E[i].to;
if(v == u_fa) continue;
dfs_1(v, u, u_deep + 1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[v]]) {
son[u] = v;
}
}
}

int c[MAXN], val[MAXN];
int sum(int i) {
int res = 0;
while(i > 0) {
res += c[i];
i -= i&(-i);
}
return res;
}
void add(int i, int val) {
while(i <= N) {
c[i] += val;
i += i&(-i);
}
}

void getpos(int u, int sp) {
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1) return ;
getpos(son[u], sp);
for(int i = head[u]; ~i; i = E[i].next) {
int &v = E[i].to;
if(v != son[u] && v != fa[u]) {
getpos(v, v);
}
}
}

void change(int u, int v, int _val) {
int f1 = top[u], f2 = top[v];
while(f1 != f2) {
if(deep[f1] < deep[f2]) {
swap(f1, f2);
swap(u, v);
}
add(p[f1], +_val);
add(p[u] + 1, -_val);
u = fa[f1];
f1 = top[u];
}
if(deep[u] > deep[v]) swap(u, v);
add(p[u], +_val);
add(p[v] + 1, -_val);
}

int main()
{
while(scanf("%d%d%d", &N, &M, &P) != EOF) {
memset(head, 0xff, sizeof head);
memset(son , 0xff, sizeof son );
memset(c   , 0x00, sizeof c   );
tot = 0; pos = 1;
for(int i = 1; i <= N; ++i) {
scanf("%d", val + i);
}
for(int i = 0; i < M; ++i) {
int x, y;
scanf("%d%d", &x, &y);
add_edge(x, y);
add_edge(y, x);
}
dfs_1(1, 0, 0);
getpos(1, 1);
for(int i = 1; i <= N; ++i) {
add(p[i], val[i]);
add(p[i] + 1, -val[i]);
}
while(P--) {
char op;
scanf("\n%c", &op);
if(op == 'Q') {
int x;
scanf("%d", &x);
printf("%d\n", sum(p[x]));
} else {
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
if(op == 'D') c = -c;
change(x, y, c);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: