hdu--3966(树链剖分)

题目链接:hdu--3966

给出n个点的值,还有n-1条边的连接方式,三种操作:

1、I在节点a到b的路径中所有的点都增加x

2、D在节点a到b的路径中所有的点都减少x

3、Q询问第k个节点的值。

将每个节点的值转化为父节点到子节点的边的权值,对于根节点做一个虚拟的父节点0 。进行树链剖分,整合到线段树中之后注意:

更新时,不能只更新a到b上的边的权值,因为那样会使b节点的权值不能被更新到,在更新a到b的段的权值后,应该在更新b到b的权值。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
#define int_now int l,int r,int rt
#define now l,r,rt
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define maxn 100000
#pragma comment(linker, "/STACK:1024000000,1024000000")
struct node
{
    int u , v ;
    int next ;
} edge[maxn<<1];
int head[maxn] , cnt , vis[maxn] ;
int num[maxn] , dep[maxn] , fa[maxn] , son[maxn] , top[maxn] , w[maxn] , step ;
int cl[maxn<<2] , lazy[maxn<<2] ;
int c[maxn] , belong[maxn] ;
void add(int u,int v)
{
    edge[cnt].u = u ;
    edge[cnt].v = v ;
    edge[cnt].next = head[u] ;
    head[u] = cnt++ ;
    return ;
}
void dfs1(int u)
{
    num[u] = 1 ;
    son[u] = -1 ;
    int i , v ;
    for(i = head[u] ; i != -1 ; i = edge[i].next)
    {
        v = edge[i].v ;
        if( vis[v] ) continue ;
        vis[v] = 1 ;
        dep[v] = dep[u] + 1 ;
        fa[v] = u ;
        dfs1(v) ;
        num[u] += num[v] ;
        if( son[u] == -1 || num[ son[u] ] < num[v] )
            son[u] = v ;
    }
    return ;
}
void dfs2(int u)
{
    if( son[u] == -1 ) return ;
    w[ son[u] ] = step++ ;
    top[ son[u] ] = top[u] ;
    vis[ son[u] ] = 1 ;
    dfs2(son[u]) ;
    int i , v ;
    for(i = head[u] ; i != -1 ; i = edge[i].next)
    {
        v = edge[i].v ;
        if( vis[v] ) continue ;
        vis[v] = 1 ;
        w[v] = step++ ;
        top[v] = v ;
        dfs2(v) ;
    }
    return ;
}
void dfs()
{
    memset(vis,0,sizeof(vis)) ;
    vis[0] = 1 ;
    dep[0] = 1 ;
    fa[0] = -1 ;
    dfs1(0) ;
    memset(vis,0,sizeof(vis)) ;
    vis[0] = 1 ;
    top[0] = 0 ;
    step = 1 ;
    dfs2(0) ;
    return ;
}
void build(int_now)
{
    cl[rt] = lazy[rt] = 0 ;
    if( l == r )
    {
        cl[rt] = c[ belong[l] ] ;
        return ;
    }
    build(lson) ;
    build(rson) ;
    return ;
}
void update(int ll,int rr,int_now,int x)
{
    if( l > rr || r < ll ) return ;
    if( ll <= l && rr >= r )
    {
        lazy[rt] += x ;
        return ;
    }
    update(ll,rr,lson,x) ;
    update(ll,rr,rson,x) ;
}
int query(int k,int_now,int sum)
{
    sum += lazy[rt] ;
    if( l == k && r == k )
    {
        return cl[rt] + sum ;
    }
    if( k <= (l+r)/2 )
        return query(k,lson,sum) ;
    else
        return query(k,rson,sum) ;
}
void solve(int u,int v,int s)
{
    int f1 , f2 ;
    while( u != v )
    {
        if( dep[u] > dep[v] )
            swap(u,v) ;
        f1 = top[u] ;
        f2 = top[v] ;
        if( f1 == f2 )
        {
            update(w[son[u]],w[v],1,step-1,1,s) ;
            v = u ;
        }
        else if( dep[f1] > dep[f2] )
        {
            update(w[f1],w[u],1,step-1,1,s) ;
            u = fa[f1] ;
        }
        else
        {
            update(w[f2],w[v],1,step-1,1,s) ;
            v = fa[f2] ;
        }
    }
    update(w[u],w[u],1,step-1,1,s) ;
    return ;
}
char str[10] ;
int main()
{
    int n , m , p ;
    int i , j  , k ;
    int u , v , s ;
    while( scanf("%d %d %d", &n, &m, &p) != EOF )
    {
        memset(head,-1,sizeof(head)) ;
        cnt = 0 ;
        for(i = 1 ; i <= n ; i++)
            scanf("%d", &c[i]) ;
        add(0,1) , add(1,0) ;
        while( m-- )
        {
            scanf("%d %d", &u, &v) ;
            add(u,v) ;
            add(v,u) ;
        }
        dfs() ;
        for(i = 1 ; i <= n ; i++)
            belong[ w[i] ] = i ;
        build(1,step-1,1) ;
        while( p-- )
        {
            scanf("%s", str) ;
            if( str[0] == 'I' )
            {
                scanf("%d %d %d", &u, &v, &s) ;
                solve(u,v,s) ;
            }
            else if( str[0] == 'D' )
            {
                scanf("%d %d %d", &u, &v, &s) ;
                solve(u,v,-s) ;
            }
            else
            {
                scanf("%d", &i) ;
                printf("%d\n", query(w[i],1,step-1,1,0)) ;
            }
        }
    }
    return 0 ;
}
时间: 2024-08-10 23:29:15

hdu--3966(树链剖分)的相关文章

HDU 3966 (树链剖分+线段树)

Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板题. 实质上树链剖分进行了点对点的一次映射,保证了重链上的点在线段树上的位置是连续的. 树链剖分的两个性质(转): 性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v]: 性质2:从根到某一点的路径上轻链.重链的个数都不大于logn. 保证了一个区间的时间复杂度是log2(n).

hdu 3966 树链剖分第3遍

真心不好意思说话,写的越多,各种问题就暴漏出来了,这次更离谱,什么错误都有...不过还是过了.也明白了代码以后要写规范性,不能想当然... #include<cstdio> #include<cstring> #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> using namespace std;

hdu 5893 (树链剖分+合并)

List wants to travel Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 429    Accepted Submission(s): 92 Problem Description A boy named List who is perfect in English. Now he wants to travel an

hdu 5052 树链剖分

Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 982    Accepted Submission(s): 274 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten too

hdu 5242 树链剖分找权值最大的前k条链

http://acm.hdu.edu.cn/showproblem.php?pid=5242 Problem Description It is well known that Keima Katsuragi is The Capturing God because of his exceptional skills and experience in ''capturing'' virtual girls in gal games. He is able to play k games sim

hdu 5274 树链剖分

Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1484    Accepted Submission(s): 347 Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i].Nodes

hdu 4897 树链剖分(重轻链)

Little Devil I Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 894    Accepted Submission(s): 296 Problem Description There is an old country and the king fell in love with a devil. The devil

HDU 5274(树链剖分)

树链剖分第一题QAQ,纪念下 #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; const ll mod = 1e9 + 7; const int maxn = 1e5 + 10; #define

HDU 5029 树链剖分

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 861    Accepted Submission(s): 219 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is f

hdu 3804树链剖分+离线操作

/* 树链刨分+离线操作 题意:给你一棵树,和询问x,y 从节点x--节点1的小于等于y的最大值. 解:先建一个空树,将树的边权值从小到大排序,将询问y按从小到大排序 对于每次询问y将小于等于y的边权值的边加入,在进行询问将结果储存最后输出即可 易错点:要考虑到节点1到节点1的情况需特判. */ #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string