hdu 3966 Aragorn's Story 树链剖分 bfs实现(不知道为什么会RE)

来源:互联网 发布:清华大学研究生 知乎 编辑:程序博客网 时间:2024/05/18 15:08

题意:给出一棵树,增加或减少树上一条路径上点的值,询问点的值


思路:学习了树链剖分,并且使用了红书的bfs版本,然后映射到线段树上,手动扩栈后还是一直RE,真的不知道怎么弄了,红书上很多数据结构在这道题没有用上,但也加上了自己的理解


希望各位神犇路过看下,不知道为什么会re


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966


#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 50010;struct edge{int u, v, next;} e[maxn << 1];int head[maxn], cnt;int in[maxn], root;void init(){cnt = 0;memset(in, 0, sizeof(in));memset(head, -1, sizeof(head));}void addedge(int u, int v){e[cnt].u = u, e[cnt].v = v, e[cnt].next = head[u], head[u] = cnt++;}int siz[maxn], dep[maxn], fa[maxn];//int len[maxn];//len[x]表示编号为x的重链的长度int son[maxn];//son[v]表示节点v的重儿子//int id[maxn];//int id[maxn];//id[x]表示节点x所在的重链中的编号,按树的深度由深至浅编号//int belong[maxn];//int belong[maxn];//belong[x]表示节点x所在的重链编号//int top[maxn];//int top[maxn];//top[x]表示编号为x的重链的顶端节点编号,那么一个节点u的重链顶端编号就是top[belong[u]]int tid[maxn];//tid[x]表示x节点及其与父节点的连边在线段树的位置int ran[maxn];//ran[x]表示线段树的x的位置是哪个节点编号int apex[maxn];//apex[x]表示x节点的所在重链的顶端节点bool vis[maxn];int q[maxn];//队列int l, r, tot;//tot为重链编号,从1开始编号int res;//res是在线段树中的编号void Clear(){memset(son, 0, sizeof(son));memset(dep, -1, sizeof(dep));//memset(vis, true, sizeof(vis));l = 0, r = 1;q[l] = root;dep[root] = 0;fa[root] = -1;tot = 0;res = 0;}void split(int n){Clear();while (l < r){int x = q[l++];vis[x] = false;for (int i = head[x]; i != -1; i = e[i].next){int v = e[i].v;if (dep[v] == -1){q[r++] = v;dep[v] = dep[x] + 1;fa[v] = x;}}}for (int i = n - 1; i >= 0; i--)//对于n个节点的一棵树来说,跑完bfs后在队列必然有是有n个点{//从后往前算,相当于dfs的回溯int x = q[i], p = -1;siz[x] = 1;for (int i = head[x]; i != -1; i = e[i].next){int v = e[i].v;if (vis[v]){siz[x] += siz[v];if (p == -1 || siz[v] > siz[p])p = v;}}if (p == -1)//表明此时的x是叶子节点{son[x] = -1;//tot++;//重链编号//len[tot] = 1;//id[x] = 1;//top[tot] = x;//belong[x] = tot;}else//p为x的重儿子{son[x] = p;//belong[x] = belong[p];//重儿子的重链编号自然是父亲的重链编号//len[belong[x]]++;//重链长度+1//id[x] = len[belong[x]];//x的在这条链的编号是目前链的长度//top[belong[x]] = x;//这条重链的顶端节点改为x}vis[x] = true;}//下面这段是将重链放置在线段树中memset(vis, false, sizeof(vis));for (int i = 0; i < n; i++){int x = q[i];if (!vis[x]){apex[x] = x;int temp = apex[x];while (!vis[x] && x != -1){vis[x] = true;apex[x] = temp;tid[x] = ++res;ran[res] = x;x = son[x];}}}}#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1int sum[maxn << 2], num[maxn], add[maxn << 2];int n, m, p;void pushdown(int rt, int len){if (add[rt]){add[rt << 1] += add[rt];add[rt << 1 | 1] += add[rt];sum[rt << 1] += add[rt] * (len - (len >> 1));sum[rt << 1 | 1] += add[rt] * (len >> 1);add[rt] = 0;}}void pushup(int rt){sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]);}void build(int l, int r, int rt){add[rt] = 0;if (l == r){sum[rt] = num[ran[l]];return;}int m = (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){add[rt] += val;sum[rt] += val * (r - l + 1);return;}pushdown(rt, r - l + 1);int m = (l + r) >> 1;if (L <= m) update(L, R, val, lson);if (m < R) update(L, R, val, rson);pushup(rt);}void change(int x, int y, int val){while (apex[x] != apex[y]){if (dep[apex[x]] < dep[apex[y]])swap(x, y);update(tid[apex[x]], tid[x], val, 1, n, 1);x = fa[apex[x]];}if (dep[x] > dep[y]) swap(x, y);update(tid[x], tid[y], val, 1, n, 1);}int query(int l, int r, int rt, int pos){if (l == r)return sum[rt];pushdown(rt, r - l + 1);int m = (l + r) >> 1;int ret = 0;if (pos <= m) ret = query(lson, pos);else ret = query(rson, pos);pushup(rt);return ret;}int main(){while (~scanf("%d%d%d", &n, &m, &p)){init();for (int i = 1; i <= n; i++)scanf("%d", &num[i]);for (int i = 0; i < m; i++){int u, v;scanf("%d%d", &u, &v);addedge(u, v);in[v]++;}for (int i = 1; i <= n; i++)//找到树的根{if (in[i] == 0){root = i;break;}}split(n);build(1, n, 1);char op[10];int a, b, c;while (p--){scanf("%s", op);if (op[0] == 'Q'){scanf("%d", &a);printf("%d\n", query(1, n, 1, tid[a]));}else{scanf("%d%d%d", &a, &b, &c);if (op[0] == 'D') change(a, b, -c);else change(a, b, c);}}}return 0;}


0 0
原创粉丝点击