【HDU 3966】树链剖分 + 线段树

剖分+线段树区间更新+单点查询

树链剖分入门题

#include <bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn = 100000+10;
int num[maxn];
int n , m , Q;

//树链剖分
int siz[maxn], top[maxn], son[maxn];
int dep[maxn], fa[maxn], tid[maxn], seg_pos[maxn];
int tim;
vector<int>es[maxn];

void Init()
{
    for(int i = 0 ; i < maxn ; i++)
    {
        es[i].clear();
    }
    tim = 0;
    memset(son, -1, sizeof(son));
}
void DFS1(int now, int from, int deep)   // 寻找重边
{
    dep[now] = deep;
    fa[now] = from;
    siz[now] = 1;
    int length = es[now].size();
    for(int i = 0 ; i < length ; i++)
    {
        int v = es[now][i];
        if(v != from)
        {
            DFS1(v, now, deep + 1);
            siz[now] += siz[v];
            if(son[now] == -1 || siz[v] > siz[son[now]])
            {
                son[now] = v;
            }
        }
    }
}

void DFS2(int now, int tp)  // 重边链接成重链
{
    top[now] = tp;
    tid[now] = ++tim; // now 在 线段树 上的编号
    seg_pos[tid[now]] = now;
    if(son[now] == -1) return;
    DFS2(son[now],tp);
    int length = es[now].size();
    for(int i = 0 ; i < length ; i++)
    {
        int v = es[now][i];
        if(v != son[now] && v != fa[now]) DFS2(v,v);
    }
}

//线段树

int sum[4*maxn],col[4*maxn];

void PushUP(int rt)
{
    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}

void PushDown(int rt,int m)
{
    if(col[rt])
    {
        col[rt<<1]+=col[rt];
        col[rt<<1|1]+=col[rt];
        sum[rt<<1]+=(m-(m>>1))*col[rt];
        sum[rt<<1|1]+=(m>>1)*col[rt];
        col[rt]=0;
    }
}

void Build(int l,int r,int rt)
{
    col[rt]=0;
    if(l==r)
    {
        sum[rt]=num[seg_pos[l]];
        return;
    }
    int mid=(l+r)>>1;
    Build(lson);
    Build(rson);
    PushUP(rt);
}

void Update(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        col[rt]+=v;
        sum[rt]+=v*(r-l+1);
        return;
    }
    PushDown(rt,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)
        Update(L,R,v,lson);
    if(R>mid)
        Update(L,R,v,rson);
    PushUP(rt);
}

int Query(int l,int r,int rt,int val)
{
    if(l==r)
        return sum[rt];
    PushDown(rt,r-l+1);
    int mid=(l+r)>>1;
    int ret=0;
    if(val<=mid) ret=Query(lson,val);
    else         ret=Query(rson,val);
    PushUP(rt);
    return ret;
}

void Change(int x, int y, int val)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x,y);
        Update(tid[top[x]], tid[x], val, 1, n, 1);
        x = fa[top[x]];
    }
    if(dep[x] < dep[y]) swap(x,y);
    Update(tid[y], tid[x], val, 1, n, 1);
}
int main()
{
    ios::sync_with_stdio(false);
    char type;
    int a,b,c;
    while(cin >> n >> m >> Q)
    {
        Init();
        for(int i=1; i<=n; i++) cin >> num[i];
        for(int i=1; i<=m; i++)
        {
            cin >> a >> b;
            es[a].push_back(b);
            es[b].push_back(a);
        }
        DFS1(1,0,0);
        DFS2(1,1);
        Build(1,n,1);
        while(Q--)
        {
            cin >> type;
            if(type=='Q')
            {
                cin >> a;
                cout << Query(1,n,1,tid[a]) << endl;
            }
            else
            {
                cin >> a >> b >> c;
                if(type=='D') c=-c;
                Change(a,b,c);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhaiqiming2010/article/details/80284373