Aragorn's Story

【原题链接】

【题意说明】

  给一定棵树,并给定各个点权的值,然后有3种操作:
  (1) I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
  (2) D C1 C2 K:把C1与C2的路径上的所有点权值减去K
  (3) Q C:查询节点编号为C的权值

【问题分析】
  
典型的树链剖分题目,先进行剖分,然后用线段树去维护即可。

【参考代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson k<<1
#define rson k<<1|1
#define lt(i) tree[i].left
#define rt(i) tree[i].right
#define nm(i) tree[i].num
#define tp(i) node[i].top
#define dp(i) node[i].deep
#define fa(i) node[i].father
#define sz(i) node[i].size
#define sn(i) node[i].son
#define id(i) node[i].index
#define hd(i) node[i].head
#define to(i) edge[i].to
#define nx(i) edge[i].next
#define vl(i) node[i].value
const int maxN=50010;
struct Tree{
         int left, right, num;
}tree[maxN<<2];
struct Node{
         int top, father, deep, size, index, head, son, value;
}node[maxN];
struct Edge{
         int to, next;
}edge[maxN<<1];
int n, m, q, total;

bool init();
void work();
void addedge(int, int, int);
void dfs1(int, int);
void dfs2(int, int);
void build(int, int, int);
void update(int, int, int, int);
int query(int, int);
void solve(int, int, int);
void pushdown(int);

int main(){
         while(init()) work();
         return 0;
}

bool init(){
         if(scanf("%d%d%d", &n, &m, &q)==EOF) return false;
         memset(tree, 0, sizeof(tree));
         memset(edge, 0, sizeof(edge));
         memset(node, 0, sizeof(node));
         total=0;
         for(int i=1; i<=n; i++) scanf("%d", &vl(i));
         for(int i=1; i<=m; i++){
                   int x, y;
                   scanf("%d%d", &x, &y);
                   addedge(x, y, i);
                   addedge(y, x, i+n);
         }
         dfs1(1, 1);
         dfs2(1, 1);
         return true;
}
void addedge(int x, int y, int k){
         to(k)=y; nx(k)=hd(x); hd(x)=k;
}

void dfs1(int k, int _dp){
         sz(k)=1; dp(k)=_dp;
         for(int i=hd(k); i; i=nx(i)){
                   if(sz(to(i))) continue;
                   fa(to(i))=k;
                   dfs1(to(i), _dp+1);
                   sz(k)+=sz(to(i));
                   if(sz(sn(k))<sz(to(i))) sn(k)=to(i);
         }
}

void dfs2(int k, int _tp){
         id(k)=++total; tp(k)=_tp;
         if(sn(k)) dfs2(sn(k), _tp);
         for(int i=hd(k); i; i=nx(i))
                   if(!id(to(i))) dfs2(to(i), to(i));
}

void work(){
         build(1, 1, n);
         for(int i=1; i<=n; i++)
                   update(1, id(i), id(i), vl(i));
         for(int i=0; i<q; i++){
                   char ch[10];
                   int u, v, w;
                   scanf("%s%d", ch, &u);
                   if(ch[0]=='Q')
                            printf("%d ", query(1, id(u)));
                   else {
                            scanf("%d%d", &v, &w);
                            if(ch[0]=='D')    w=-w;
                            solve(u, v, w);
                   } 
         }
}

void build(int k, int l, int r){
         lt(k)=l; rt(k)=r;
         if(l==r) return;
         int mid=(l+r)>>1;
         build(lson, l, mid);
         if(mid<r) build(rson, mid+1, r);
}

void solve(int u, int v, int w){
         int f1=tp(u), f2=tp(v);
         while(f1!=f2){
                   if(dp(f1)<dp(f2)){
                            swap(f1, f2);
                            swap(u, v);
                   }
                   update(1, id(f1), id(u), w);
                   u=fa(f1); f1=tp(u);
         }
         if(dp(u)<dp(v)) swap(u, v);
         update(1, id(v), id(u), w);
}

void update(int k, int l, int r, int v){
         if(l<=lt(k)&&r>=rt(k)){
                   nm(k)+=v; return;
         }
         pushdown(k);
         if(l<=rt(lson)) update(lson, l, r, v);
         if(r>=lt(rson)) update(rson, l, r, v);
}

void pushdown(int k){
         if(nm(k)){
                   nm(lson)+=nm(k);
                   nm(rson)+=nm(k);
                   nm(k)=0;
         }
}

int query(int k, int x){
         if(lt(k)==rt(k)) return nm(k);
         pushdown(k);
         if(x<=rt(lson)) return query(lson, x);
         return query(rson, x);
}

原文地址:https://www.cnblogs.com/ahmasoi/p/6678395.html