Aragorn's Story

題目:Aragorn’s Story

樹鏈剖分模板

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <string.h>
#include <iostream>
#include <algorithm>
#define pi 3.14159265358979
#define mid (left+right)/2
#define ls (2*rt)
#define rs ((2*rt)+1)
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int N = 5e4+5;
const int inf = 0x7FFFFFFF;
const int mod = 998244353;

int read(){
    char ch=getchar();int x=0,f=1;
    while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

vector<int>G[N];
int w[N],step[N],fa[N],size[N],son[N];
int id[N],wt[N],top[N];
int tree[N<<2];

void dfs1(int u,int f,int deep){
    step[u] = deep;//紀錄位於哪一層
    fa[u] = f;//記錄父親結點
    size[u] = 1;//記錄非葉子結點的子樹大小
    int maxson = -1;//記錄重兒子的兒子數
    int n = G[u].size();
    for(int i = 0;i < n;i++){
        int v = G[u][i];
        if(v == f) continue;
        dfs1(v,u,deep+1);
        size[u] += size[v];//加上它兒子的個數
        if(size[v] > maxson){
            maxson = size[v];
            son[u] = v;//記錄非葉子節點重兒子的編號
        }
    }
}
int cnt = 0;
void dfs2(int u,int topf){//u是當前結點,topf是當前鏈的最頂端的節點 
    id[u] = ++cnt;//標記每個點的新編號
    wt[cnt] = w[u];
    top[u] = topf;//這個點所在鏈的頂端
    if(!son[u]) return;//如果沒有兒子返回
    dfs2(son[u],topf);//對於非葉子節點,優先處理重兒子,再處理輕兒子
    int n = G[u].size();
    for(int i = 0;i < n;i++){
        int v = G[u][i];
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v,v);//對於每一個輕兒子都有一條從它自己開始的鏈         
    }
}
void build(int rt,int left,int right){
    if(left == right){
        tree[rt] = wt[left];
        return;
    }
    build(ls,left,mid);
    build(rs,mid+1,right);
    
}

void pushdown(int rt){
    tree[ls] += tree[rt];
    tree[rs] += tree[rt];
    tree[rt] = 0;
}
void update(int rt,int left,int right,int l,int r,int k){
    if(left >= l && right <= r){
        tree[rt] += k;
        return;
    }
    if(tree[rt]) pushdown(rt);
    if(l <= mid) update(ls,left,mid,l,r,k);
    if(r > mid) update(rs,mid+1,right,l,r,k);
}
void updrange(int x,int y,int k,int n){
    while(top[x] != top[y]){
        if(step[top[x]] < step[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x = fa[top[x]];
    }
    if(step[x] > step[y]) swap(x,y);
    update(1,1,n,id[x],id[y],k);
}

int query(int rt,int left,int right,int k){
    if(left == right){
        return tree[rt];
    }
    if(tree[rt]) pushdown(rt);
    if(k <= mid) return query(ls,left,mid,k);
    else return query(rs,mid+1,right,k);
}

void solve(int n,int m,int q){
    for(int i = 1;i <= n;i++){
        w[i] = read();
    }
    for(int i = 1;i <= m;i++){
        int u = read();
        int v = read();
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n);
    /*
    for(int i = 1;i <= n;i++){
        printf("%3d",w[i]);
    }
    cout<<endl;
    for(int i = 1;i <= n;i++){
        printf("%3d",id[i]);
    }
    cout<<endl;
    for(int i = 1;i <= n;i++){
        printf("%3d",wt[i]);
    }
    cout<<endl;
    */
    while(q--){
        char op;
        cin >> op;
        if(op == 'I'){
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            updrange(l,r,k,n);
        }else if(op == 'D'){
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            updrange(l,r,-1*k,n);
        }else if(op == 'Q'){
            int u;
            scanf("%d",&u);
            cout<<query(1,1,n,id[u])<<endl;
        }
    }
}



void init(){
    cnt = 0;
    for(int i = 0;i < N;i++) G[i].clear();
    memset(tree,0,sizeof tree);
    memset(top,0,sizeof top);
    memset(wt,0,sizeof wt);
    memset(id,0,sizeof id);
    memset(son,0,sizeof son);
    memset(size,0,sizeof size);
    memset(fa,0,sizeof fa);
    memset(step,0,sizeof step);
}
int main(){
    int n,m,q;
    while(~scanf("%d%d%d",&n,&m,&q)){
        init();
        solve(n,m,q);
    }
    return 0;
}
/*
8 7
5 10 7 15 8 20 11 9
1 2
1 4
2 3
2 6
4 5
4 8
5 7

3 2 5
1 2 3
2 1
2 3
1 1 3 5
3 2
2 1 2 2
3 1 
3 3
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章