zoukankan      html  css  js  c++  java
  • HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044

    题目大意:修改链上点,修改链上的边。查询所有点,查询所有边。

    解题思路

    2014上海网赛的变态树链剖分模板题。将以往树链剖分的点&边修改和查询合在一起之后,难度上去不少。

    第一个卡人点是读入优化。

    第二个卡人点是树状数组。由于要查询所有点,如果使用线段树,每次都要扫到底层才能取出点值,必T无疑。

    然后使用树状数组之后,树链剖分的点/边修改写法有些变动。

    点查询变化不大。

    边查询只要查询一下dep(u,v)大的那一端。

    具体变化请仔细看代码。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include "cstdio"
    #include "cstring"
    #include "iostream"
    using namespace std;
    #define maxn 100005
    template <class T>
    inline bool read(T &ret)
    {
        char c;
        int sgn;
        if(c=getchar(),c==EOF) return 0; //EOF
        while(c!='-'&&(c<'0'||c>'9')) c=getchar();
        sgn=(c=='-')?-1:1;
        ret=(c=='-')?0:(c-'0');
        while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
        ret*=sgn;
        return 1;
    }
    int s[maxn],dep[maxn],w[maxn],fa[maxn],top[maxn],son[maxn],tol,cnt,n,head[maxn];
    struct Edge
    {
        int u,v,c;
    }edge[maxn];
    struct EDGE
    {
        int next,to;
    }e[2*maxn];
    void addedge(int u,int v)
    {
        e[tol].to=v;
        e[tol].next=head[u];
        head[u]=tol++;
    }
    void dfs1(int u,int pre,int d)
    {
        s[u]=1;fa[u]=pre;dep[u]=d;son[u]=-1;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(v==pre) continue;
            dfs1(v,u,d+1);
            s[u]+=s[v];
            if(son[u]!=-1||s[v]>s[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u,int tp)
    {
        w[u]=++cnt;top[u]=tp;
        if(son[u]!=-1) dfs2(son[u],tp);
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
        }
    }
    //Binary-Indexed-Tree type:0-point,1-edge
    int psum[maxn],esum[maxn];
    inline int lowbit(int x) {return x&(-x);}
    int sum(int x,int type)
    {
        int ret=0;
        while(x>0)
        {
            if(!type) ret+=psum[x];
            else ret+=esum[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void add(int x,int d,int type)
    {
        while(x<=n)
        {
            if(!type) psum[x]+=d;
            else esum[x]+=d;
            x+=lowbit(x);
        }
    }
    void p_Change(int x,int y,int v)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            add(w[top[x]],v,0);
            add(w[x]+1,-v,0);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        add(w[x],v,0);
        add(w[y]+1,-v,0);
    }
    void e_Change(int x,int y,int v)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            add(w[top[x]],v,1);
            add(w[x]+1,-v,1);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        if(x!=y) //这个判断非常重要,没有的话T死你
        {
            add(w[son[x]],v,1);
            add(w[y]+1,-v,1);
        }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T,u,v,c,m,no=0;
        char cmd[10];
        read(T);
        while(T--)
        {
            memset(head,-1,sizeof(head));
            memset(esum,0,sizeof(esum));
            memset(psum,0,sizeof(psum));
            tol=cnt=0;
            read(n);read(m);
            for(int i=1;i<n;i++)
            {
                read(edge[i].u);read(edge[i].v);
                addedge(edge[i].u,edge[i].v);
                addedge(edge[i].v,edge[i].u);
            }
            dfs1(1,1,1);
            dfs2(1,1);
            for(int i=1;i<n;i++)
              if(dep[edge[i].u]<dep[edge[i].v]) swap(edge[i].u,edge[i].v);
            while(m--)
            {
                scanf("%s",cmd);
                read(u);read(v);read(c);
                if(cmd[3]=='1') p_Change(u,v,c);
                if(cmd[3]=='2') e_Change(u,v,c);
            }
            printf("Case #%d:
    ",++no);
            for(int i=1;i<=n;i++) {if(i>=2) printf(" ");printf("%d",sum(w[i],0));}
            printf("
    ");
            for(int i=1;i<n;i++) {if(i>=2) printf(" ");printf("%d",sum(w[edge[i].u],1));}
            printf("
    ");
        }
    }
    11824525 2014-10-08 17:34:00 Accepted 5044 3718MS 11576K 3384 B C++ Physcal
  • 相关阅读:
    iOS 解析xml
    带滚动条html,js获取鼠标位置
    iOS ViewController利用代理页面传值
    Android Volley完全解析
    32位linux中无法使用AVD的解决方案
    8年前在公交上被年轻小伙打了,76岁大爷苦练功夫“复仇”成功...网友:大爷,你一定是天蝎座的吧
    退学,离家出走,卖房创业,在他即将烧完最后一笔钱时,获250万元融资
    夏普将在迪拜推出植物工厂种草莓
    国产手机出货量今年要追平苹果三星,到底有多难?
    原生ajax动态添加数据
  • 原文地址:https://www.cnblogs.com/neopenx/p/4011734.html
Copyright © 2011-2022 走看看