• HDU3966(树链剖分)


    题目:Aragorn's Story

    题意:给一棵树,并给定各个点权的值,然后有3种操作:

    I C1 C2 K: 把C1与C2的路径上的所有点权值加上K

    D C1 C2 K:把C1与C2的路径上的所有点权值减去K

    Q C:查询节点编号为C的权值

    分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易爆栈,所以在代码

    前面加上:#pragma comment(linker, "/STACK:1024000000,1024000000")进行手动扩栈。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    #include <vector>
    
    using namespace std;
    const int N=50010;
    
    int n,m,Q;
    int tim;
    
    int num[N],siz[N],top[N],son[N];
    int dep[N],tid[N],rank[N],fa[N];
    int head[N],to[2*N],next[2*N],edge;
    
    void Init()
    {
        memset(head,-1,sizeof(head));
        memset(son,-1,sizeof(son));
        tim=0;
        edge=0;
    }
    
    void addedge(int u,int v)
    {
        to[edge]=v,next[edge]=head[u],head[u]=edge++;
        to[edge]=u,next[edge]=head[v],head[v]=edge++;
    }
    
    //树链剖分部分
    void dfs1(int u,int father,int d)
    {
        dep[u]=d;
        fa[u]=father;
        siz[u]=1;
        for(int i=head[u];~i;i=next[i])
        {
            int v=to[i];
            if(v!=father)
            {
                dfs1(v,u,d+1);
                siz[u]+=siz[v];
                if(son[u]==-1||siz[v]>siz[son[u]])
                    son[u]=v;
            }
        }
    }
    
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        tid[u]=++tim;
        rank[tid[u]]=u;
        if(son[u]==-1) return;
        dfs2(son[u],tp);
        for(int i=head[u];~i;i=next[i])
        {
            int v=to[i];
            if(v!=son[u]&&v!=fa[u])
                dfs2(v,v);
        }
    }
    
    //线段树部分
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    int sum[4*N],col[4*N];
    
    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[rank[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[x],tid[y],val,1,n,1);
    }
    
    int main()
    {
        char oper[5];
        int a,b,c;
        while(~scanf("%d%d%d",&n,&m,&Q))
        {
            Init();
            for(int i=1;i<=n;i++)
               scanf("%d",&num[i]);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                addedge(a,b);
            }
            dfs1(1,0,0);
            dfs2(1,1);
            Build(1,n,1);
            while(Q--)
            {
                scanf("%s",oper);
                if(oper[0]=='Q')
                {
                    scanf("%d",&a);
                    printf("%d
    ",Query(1,n,1,tid[a]));
                }
                else
                {
                    scanf("%d%d%d",&a,&b,&c);
                    if(oper[0]=='D') c=-c;
                    Change(a,b,c);
                }
            }
        }
        return 0;
    }
    


     

  • 相关阅读:
    代码审计之越权及越权
    代码审计之XSS及修复
    代码审计之SQL注入及修复
    代码审计之CSRF原理及修复
    挖穿各大SRC的短信轰炸
    Kerberoasting攻击
    SPN扫描
    Windows认证 | 域认证
    Windows认证 | 网络认证
    Ceph 纠删码介绍
  • 原文地址:https://www.cnblogs.com/james1207/p/3292318.html
Copyright © 2020-2023  润新知