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
原创粉丝点击