• HDU 3966 Aragorn's Story --树链剖分


    题意: 树上路径之间的点统一加减k,查询某点的值

    解法:不会LCA的解法,于是用树链剖分了,比较简单的剖分,然后用线段树维护就行了,相当于区间更新,单点查询,查询点 i 的值时,只需在线段树中查询pos[u]位置的值即可。

    加IO优化900+ms

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define N 50007
    
    int siz[N];  //子树大小
    int son[N];  //重儿子
    int dep[N];  //深度
    int pos[N];  //在线段树中的位置
    int Top[N];  //所在重链的祖先
    int fa[N];   //父节点
    int head[2*N],tot,POS,n,m,q;
    struct Edge
    {
        int v,next;
    }G[2*N];
    int tree[4*N],mark[4*N],a[N];
    
    void init()
    {
        POS = tot = 0;
        memset(head,-1,sizeof(head));
        memset(son,-1,sizeof(son));
        memset(tree,0,sizeof(tree));
        memset(mark,0,sizeof(mark));
    }
    
    void addedge(int u,int v)
    {
        G[tot].v = v, G[tot].next = head[u], head[u] = tot++;
        G[tot].v = u, G[tot].next = head[v], head[v] = tot++;
    }
    
    void pushdown(int l,int r,int rt)
    {
        int mid = (l+r)/2;
        if(mark[rt])
        {
            mark[2*rt] += mark[rt];
            mark[2*rt+1] += mark[rt];
            tree[2*rt] += mark[rt]*(mid-l+1);
            tree[2*rt+1] += mark[rt]*(r-mid);
            mark[rt] = 0;
        }
    }
    
    void update(int l,int r,int aa,int bb,int k,int rt)
    {
        if(aa <= l && bb >= r)
        {
            tree[rt] += k*(r-l+1);
            mark[rt] += k;
            return;
        }
        int mid = (l+r)/2;
        if(aa <= mid)
            update(l,mid,aa,bb,k,2*rt);
        if(bb > mid)
            update(mid+1,r,aa,bb,k,2*rt+1);
    }
    
    int query(int l,int r,int pos,int rt)
    {
        if(l == r)
            return tree[rt];
        pushdown(l,r,rt);
        int mid = (l+r)/2;
        if(pos <= mid) return query(l,mid,pos,2*rt);
        else return query(mid+1,r,pos,2*rt+1);
    }
    
    void dfs(int u,int f)
    {
        dep[u] = dep[f]+1;
        siz[u] = 1;
        for(int i=head[u];i!=-1;i=G[i].next)
        {
            int v = G[i].v;
            if(v == f) continue;
            fa[v] = u;
            dfs(v,u);
            if(son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
            siz[u] += siz[v];
        }
    }
    
    void dfs2(int u,int father)
    {
        pos[u] = ++POS;
        Top[u] = father;
        if(son[u] != -1) dfs2(son[u],father);
        for(int i=head[u];i!=-1;i=G[i].next)
        {
            int v = G[i].v;
            if(v != fa[u] && v != son[u])
                dfs2(v,v);
        }
    }
    
    void Change(int u,int v,int k)
    {
        int fx = Top[u], fy = Top[v];
        while(fx != fy)
        {
            if(dep[fx] < dep[fy])
            {
                swap(u,v);
                swap(fx,fy);
            }
            update(1,POS,pos[fx],pos[u],k,1);
            u = fa[fx];
            fx = Top[u];
        }
        if(dep[u] > dep[v]) swap(u,v);
        update(1,POS,pos[u],pos[v],k,1);
    }
    
    inline int in()
    {
        char ch;
        int a = 0;
        while((ch = getchar()) == ' ' || ch == '
    ');
        a += ch - '0';
        while((ch = getchar()) != ' ' && ch != '
    ')
        {
            a *= 10;
            a += ch - '0';
        }
        return a;
    }
    
    int main()
    {
        int u,v,k,i;
        char ss[5];
        while(scanf("%d%d%d",&n,&m,&q)!=EOF)
        {
            init();
            for(i=1;i<=n;i++)
                a[i] = in();
            for(i=1;i<n;i++)
            {
                u = in(), v = in();
                addedge(u,v);
            }
            dep[0] = 0;
            dfs(1,0);
            dfs2(1,1);
            for(i=1;i<=n;i++)
                update(1,POS,pos[i],pos[i],a[i],1);
            while(q--)
            {
                scanf("%s",ss);
                if(ss[0] == 'Q')
                {
                    u = in();
                    printf("%d
    ",query(1,POS,pos[u],1));
                }
                else
                {
                    u = in(), v = in(), k = in();
                    if(ss[0] == 'I')
                        Change(u,v,k);
                    else
                        Change(u,v,-k);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    js rsa sign使用笔记(加密,解密,签名,验签)
    金额的计算
    常用js方法集合
    sourceTree 的使用
    node-- express()模块
    详细讲解vue.js里的父子组件通信(props和$emit)
    Vue -- vue-cli webpack打包开启Gzip 报错
    es6函数的rest参数和拓展运算符(...)的解析
    js中判断对象数据类型的方法
    vue学习之vue基本功能初探
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4009374.html
Copyright © 2020-2023  润新知