HDU 3966 树链剖分
来源:互联网 发布:直播刷屏软件 编辑:程序博客网 时间:2024/05/16 15:27
HDU 3966
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:
n个(<=1e5)兵营,以树的形式相互连接构成连通图。给出初始每个兵营的兵数量。
然后有修改操作,即u-v的路径上(包括u,v)经过的兵营兵的数量全减少或增加某一个值。
有查询操作,求一个兵营当前兵的数量。输出这个数量。
思路:
裸的树链剖分。
各种写错。
容易T的地方:
1)solve处的u=fa[tp1]写成u=fa[u]
2)Solve处各种写反
容易WA的地方:
1)solve处u=v则退出
2)建线段树时,tree[o].val = val[id[l]]而不是tree[o].val = val[tid[l]](要用一个新的指针指回去,搞清楚线段树中这个点到底是哪一个点)
3)线段树更新时没有及时push_down。
源码:
#pragma comment(linker,"/STACK:100000000,100000000")#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <iostream>#include <vector>#include <queue>using namespace std;const int MAXN = 50000 + 5;int tp[MAXN], fa[MAXN], num[MAXN], son[MAXN], dep[MAXN];int id[MAXN], cnt, tid[MAXN];vector<int>lin[MAXN];void dfs1(int u, int f, int deep){ num[u] = 1, fa[u] = f, son[u] = 0, dep[u] = deep; for(int i = 0 ; i < (int)lin[u].size() ; i++){ int v = lin[u][i]; if(v == f) continue; dfs1(v, u, deep + 1); num[u] += num[v]; if(num[son[u]] < num[v]) son[u] = v; }}void dfs2(int u, int f){ id[u] = ++cnt; tid[cnt] = u; tp[u] = f; if(son[u]) dfs2(son[u], f); for(int i = 0 ; i < (int)lin[u].size() ; i++){ int v = lin[u][i]; if(v == fa[u] || v == son[u]) continue; dfs2(v, v); }}struct Tree{ int l, r, val; int add;}tree[MAXN * 4];int val[MAXN];void build(int l, int r, int o){ tree[o].l = l, tree[o].r = r, tree[o].add = 0, tree[o].val = 0; if(l == r){ tree[o].val = val[tid[l]]; return; } int mid = (l + r) / 2; if(mid >= l) build(l, mid, o * 2); if(mid < r) build(mid + 1, r, o * 2 + 1);}void push_down(int o){ if(tree[o].add == 0) return; tree[o * 2].add += tree[o].add; tree[o * 2 + 1].add += tree[o].add; tree[o].add = 0;}int query(int u, int o){// printf("u = %d, o = %d\n", u, o);// printf("tree[o].l = %d, tree[o].r = %d\n", tree[o].l, tree[o].r);// system("pause"); if(tree[o].l == tree[o].r && tree[o].l == u){ return tree[o].add + tree[o].val; } int ans = 0; push_down(o); int mid = (tree[o].l + tree[o].r) / 2; if(mid >= u) ans = query(u, o * 2); else ans = query(u, o * 2 + 1); return ans;}void update(int l, int r, int val, int o){// if(tree[o].r < l || tree[o].l > r) return;// printf("l = %d, r = %d, val = %d, tree[o].l = %d, tree[o].r = %d, o = %d\n", l, r, val, tree[o].l, tree[o].r, o);// system("pause"); if(tree[o].l >= l && tree[o].r <= r){ tree[o].add += val; return; } push_down(o); int mid = (tree[o].l + tree[o].r) / 2; if(mid < l) update(l, r, val, o * 2 + 1); else if(mid >= r) update(l, r, val, o * 2); else{ update(l, r, val, o * 2); update(l, r, val, o * 2 + 1); }}void solve(int u, int v, int val){ int tp1 = tp[u], tp2 = tp[v]; while(tp1 != tp2){ if(dep[tp1] < dep[tp2]) swap(tp1, tp2), swap(u, v); update(id[tp1], id[u], val, 1); u = fa[tp1]; tp1 = tp[u]; } if(dep[u] > dep[v]) swap(u, v); update(id[u], id[v], val, 1);}char op[1000];int main(){ int n, m, q; while(scanf("%d%d%d", &n, &m, &q) != EOF){ for(int i = 0 ; i <= n ; i++) lin[i].clear(); int u, v, w; for(int i = 1 ; i <= n ; i++) scanf("%d", &val[i]); for(int i = 0 ; i < m ; i++){ scanf("%d%d", &u, &v); lin[u].push_back(v); lin[v].push_back(u); } cnt = 0; dfs1(1, 0, 1); dfs2(1, 1); build(1, n, 1); while(q--){ scanf("%s", op); if(op[0] == 'Q'){ scanf("%d", &u);// printf("first = %d, second = %d\n", query(id[u], 1), val[id[u]]); printf("%d\n", query(id[u], 1)); } else{ scanf("%d%d%d", &u, &v, &w); if(op[0] == 'D') solve(u, v, -w); else solve(u, v, w); } } } return 0;}
0 0
- HDU 3966 树链剖分
- hdu 3966 树链剖分模版
- hdu 3966 树链剖分
- hdu--3966(树链剖分)
- HDU 3966 树链剖分学习
- HDU 3966 树链剖分模板
- hdu 3966(树链剖分)
- HDU 3966 树链剖分
- HDU 3966 树链剖分
- hdu 3966(树链剖分)
- HDU 3966 树链剖分
- HDU 3966 [树链剖分]
- 树链剖分 HDU 3966
- HDU-3966-树链剖分
- hdu 3966 树链剖分
- hdu 3966 树链剖分
- hdu 3966 (树链剖分+线段树)
- hdu 3966 树链剖分+线段树
- Java解析HTML之HTMLParser使用与详解
- RecyclerView添加Header的正确方式
- 快两年了,重拾起android.
- JDK DualPivotQuicksort 源码解析
- Spark学习1—记录笔记
- HDU 3966 树链剖分
- 网站设计
- Spring配置文件的使用
- php显示TABLE数据
- User32.dll 中的函数
- Andorid--gps provider获取
- C++继承、虚继承、虚函数类的大小问题
- POJ 1611 The Suspects (并查集)
- ListView初步