HDU

来源:互联网 发布:赫鲁晓夫 知乎 编辑:程序博客网 时间:2024/06/09 18:43

题意:给你一颗树,每个节点都有点权,有两个操作

1、求某个点的点权。

2、给出两个点u,v和一个值value,将由点u到点v路径上的点的权值+value(包括u,v)。

节点数 <= 5e4 操作数 <= 1e5初始边权 <= 1e3|value| <= 1e3


树链剖分的入门题,今天刚学了树链剖分。感觉树剖还是很有用的,毕竟把一棵树上的操作转化成对于一个区间的操作,会简单方便很多。

今天看了不少的博客,感觉比之前收获了很多,之前某些不太明白的,现在都明白的差不多了,至于掌握了多少,就需要试试才知道了

其实这个题并不一定需要线段树维护,我们用一个树状数组维护就可以了,这里我是为了试试树剖和线段树结合自己的码力较弱,所以需要练习。


#pragma comment(linker, "/STACK:1024000000,1024000000")  #include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long LL;const int INF = 0x3f3f3f3f;const int maxn = 5e4+10;int N,M,P;int head[maxn],val[maxn];int tot,edge_cnt;struct Edge{int to,next;}edge[maxn<<1];void ADD(int u,int v){edge[edge_cnt].to = v;edge[edge_cnt].next = head[u];head[u] = edge_cnt++;}int size[maxn];//子树的节点个数int fa[maxn];//父亲节点int son[maxn];//重孩子节点int deep[maxn];//节点的深度int top[maxn];//重链的端点int id[maxn];//剖分后节点的序号int Rank[maxn];//最初的位置void dfs1(int now,int father,int Deep){size[now] = 1;fa[now] = father;deep[now] = Deep;son[now] = 0;for(int i = head[now]; ~i; i = edge[i].next){int v = edge[i].to;if(v != father){dfs1(v,now,Deep+1);size[now] += size[v];if(size[v] > size[son[now]])son[now] = v;}}}void dfs2(int now,int Top){id[now] = ++tot;top[now] = Top;Rank[id[now]] = now;if(son[now])dfs2(son[now],Top);for(int i = head[now]; ~i; i = edge[i].next){int v = edge[i].to;if(v != fa[now] && v != son[now]){dfs2(v,v);}}}struct node{int l,r,value;int lazy;};struct SGT{node tree[maxn<<2];void build(int root,int l,int r){tree[root].lazy = 0;tree[root].l = l;tree[root].r = r;if(l == r){tree[root].value = val[Rank[l]];return;}int Mid = (l+r)>>1;build(root<<1,l,Mid);build(root<<1|1,Mid+1,r);}void pushDown(int root){tree[root<<1].value += tree[root].lazy;tree[root<<1|1].value += tree[root].lazy;tree[root<<1].lazy += tree[root].lazy;tree[root<<1|1].lazy += tree[root].lazy;tree[root].lazy = 0;}void update(int root,int l,int r,int value){if(l <= tree[root].l && tree[root].r <= r){tree[root].value += value;tree[root].lazy += value;return;}int Mid = (tree[root].l+tree[root].r)>>1;pushDown(root);if(l <= Mid)update(root<<1,l,r,value);if(Mid < r)update(root<<1|1,l,r,value);}int query(int root,int idx){if(tree[root].l == tree[root].r)return tree[root].value;int Mid = (tree[root].l+tree[root].r)>>1;pushDown(root);if(idx <= Mid)return query(root<<1,idx);elsereturn query(root<<1|1,idx);}};SGT sgt;void work(int u,int v,int w){int tpu = top[u];int tpv = top[v];while(tpu != tpv){if(deep[tpu] < deep[tpv]){swap(tpu,tpv);swap(u,v);}sgt.update(1,id[tpu],id[u],w);u = fa[tpu];tpu = top[u];}if(deep[u]>deep[v]){swap(u,v);}sgt.update(1,id[u],id[v],w);}int main(){char op[5];while(~scanf("%d %d %d",&N,&M,&P)){tot = 0;edge_cnt = 0;memset(head,-1,sizeof(head));for(int i = 1; i <= N; i++)scanf("%d",&val[i]);for(int i = 0; i < N-1; i++){int u,v;scanf("%d %d",&u,&v);ADD(u,v);ADD(v,u);}dfs1(1,0,0);dfs2(1,1);sgt.build(1,1,N);int u,v,w;while(P--){scanf("%s",op);if(op[0] == 'Q'){scanf("%d",&u);printf("%d\n",sgt.query(1,id[u]));}else{scanf("%d %d %d",&u,&v,&w);if(op[0] == 'D')w = -w;work(u,v,w);}}}return 0;}


原创粉丝点击