[kuangbin]树链剖分A

比较水的题了,比模板题还要简单一点

理解了这个结构,自己打出来的,但是小错误还是很多,越来越熟练吧希望

错误函数updata,updata_lca,query||错误地方区间往下递归的时候是left <= mid || right > mid

//https://vjudge.net/contest/251031#problem
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#define lson rt<<1,left,mid
#define rson rt<<1|1,mid+1,right
#define ls rt<<1
#define rs rt<<1|1
//#define mid ((left + right) >> 1)
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 1e3;
int n,m,p;
int V[maxn];
//邻接表
struct node{
    int to,pre;
}e[maxn << 1];
int id[maxn],cnt;
//线段树
int val[maxn << 2],lazy[maxn<<2];
//dfs1
int siz[maxn],dep[maxn],fa[maxn],son[maxn];
//dfs2
int top[maxn],num_id[maxn],id_num[maxn];
int tot;
void init()
{
    memset(id,-1,sizeof(id));
    memset(son,0,sizeof(son));
    cnt = tot = 0;
}
void add(int from,int to)
{
    e[cnt].to = to;
    e[cnt].pre = id[from];
    id[from] = cnt++;
}
void dfs1(int now,int f,int depth)
{
    siz[now] = 1;
    fa[now] = f;
    dep[now] = depth;

    for(int i = id[now];~i;i = e[i].pre)
    {
        int to = e[i].to;
        if(to != f)
        {
            dfs1(to,now,depth+1);
            siz[now] += siz[to];
            if(siz[to] > siz[son[now]])
                son[now] = to;
        }
    }
}
void dfs2(int now,int rt)
{
    top[now] = rt;
    num_id[now] = ++tot;
    id_num[tot] = now;

    if(!son[now]) return;

    dfs2(son[now],rt);

    for(int i = id[now];~i;i = e[i].pre)
    {
        int to = e[i].to;
        if(to != son[now] && to != fa[now])
        {
            dfs2(to,to);
        }
    }
}
void pup(int rt)
{
    val[rt] = val[ls] + val[rs];
}
void build(int rt,int left,int right)
{
    lazy[rt] = 0;

    if(left == right)
    {
        val[rt] = V[id_num[left]];
        return;
    }
    int mid = (left + right) >> 1;
    build(lson);build(rson);
    pup(rt);
}
void pdown(int rt,int left,int right)
{
    if(lazy[rt])
    {
        int lt = lazy[rt];
        int mid = (left + right) >> 1;
        val[ls] += (mid - left + 1) * lt;
        val[rs] += (right - mid) * lt;
        lazy[rs] += lt;
        lazy[ls] += lt;
        lazy[rt] = 0;
    }
}
void updata(int rt,int left,int right,int l,int r,int k)
{
    if(left > r || right < l)return;
    if(l <= left && right <= r)
    {
        val[rt] += (right - left + 1) * k;
        lazy[rt] += k;
        return;
    }
    pdown(rt,left,right);

    int mid = (left + right) >> 1;

    if(left <= mid)
        updata(lson,l,r,k);
    if(right > mid)
        updata(rson,l,r,k);
}
void updata_lca(int x,int y,int k)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]])swap(x,y);
        updata(1,1,tot,num_id[top[x]],num_id[x],k);
        x = fa[top[x]];
    }
    if(dep[x] < dep[y])swap(x,y);
    updata(1,1,tot,num_id[y],num_id[x],k);
}
int query(int rt,int left,int right,int l,int r)
{
    int res = 0;
    if(left > r || right < l)return 0;

    if(l <= left && right <= r)
    {
        return val[rt];
    }

    pdown(rt,left,right);

    int mid = (left + right) >> 1;
    if(left <= mid)res += query(lson,l,r);
    if(right > mid)res += query(rson,l,r);

    return res;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&p))
    {
        init();
        for(int i = 1;i <= n;++i)
        {
            scanf("%d",&V[i]);
        }
        int from,to;
        for(int i = 1;i <= m;++i)
        {
            scanf("%d%d",&from,&to);
            add(from,to);
            add(to,from);
        }
        dfs1(1,1,1);
        //忘记init
        dfs2(1,1);
        build(1,1,tot);
        //cout<<val[1]<<" "<<val[2]<<" "<<val[3]<<" "<<val[4]<<" "<<val[5]<<endl;正确建树
        char op[2];
        int x,y,z;
        for(int i = 0;i < p;++i)
        {
            scanf("%s",op);
            if(op[0] == 'I')
            {
                scanf("%d%d%d",&x,&y,&z);
                updata_lca(x,y,z);
            }
            else if(op[0] == 'D')
            {
                scanf("%d%d%d",&x,&y,&z);
                //cout<<num_id[x]<<" "<<num_id[y]<<endl;
                updata_lca(x,y,-z);
            }
            else
            {
                scanf("%d",&x);
                //cout<<num_id[x]<<endl;对
                printf("%d
",query(1,1,tot,num_id[x],num_id[x]));
            }
        }
    }
    return 0;
}
/*
3 2 500
1 2 3
2 1
2 3
*/
原文地址:https://www.cnblogs.com/DF-yimeng/p/9582833.html