zoukankan      html  css  js  c++  java
  • [kuangbin]树链剖分A

    比较水的题了,比模板题还要简单一点

    理解了这个结构,自己打出来的,但是小错误还是很多,越来越熟练吧希望

    错误函数updata,updata_lca,query||错误地方区间往下递归的时候是left <= mid || right > mid

    //https://vjudge.net/contest/251031#problem
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    #include <cmath>
    #define lson rt<<1,left,mid
    #define rson rt<<1|1,mid+1,right
    #define ls rt<<1
    #define rs rt<<1|1
    //#define mid ((left + right) >> 1)
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 1e3;
    int n,m,p;
    int V[maxn];
    //邻接表
    struct node{
        int to,pre;
    }e[maxn << 1];
    int id[maxn],cnt;
    //线段树
    int val[maxn << 2],lazy[maxn<<2];
    //dfs1
    int siz[maxn],dep[maxn],fa[maxn],son[maxn];
    //dfs2
    int top[maxn],num_id[maxn],id_num[maxn];
    int tot;
    void init()
    {
        memset(id,-1,sizeof(id));
        memset(son,0,sizeof(son));
        cnt = tot = 0;
    }
    void add(int from,int to)
    {
        e[cnt].to = to;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    void dfs1(int now,int f,int depth)
    {
        siz[now] = 1;
        fa[now] = f;
        dep[now] = depth;
    
        for(int i = id[now];~i;i = e[i].pre)
        {
            int to = e[i].to;
            if(to != f)
            {
                dfs1(to,now,depth+1);
                siz[now] += siz[to];
                if(siz[to] > siz[son[now]])
                    son[now] = to;
            }
        }
    }
    void dfs2(int now,int rt)
    {
        top[now] = rt;
        num_id[now] = ++tot;
        id_num[tot] = now;
    
        if(!son[now]) return;
    
        dfs2(son[now],rt);
    
        for(int i = id[now];~i;i = e[i].pre)
        {
            int to = e[i].to;
            if(to != son[now] && to != fa[now])
            {
                dfs2(to,to);
            }
        }
    }
    void pup(int rt)
    {
        val[rt] = val[ls] + val[rs];
    }
    void build(int rt,int left,int right)
    {
        lazy[rt] = 0;
    
        if(left == right)
        {
            val[rt] = V[id_num[left]];
            return;
        }
        int mid = (left + right) >> 1;
        build(lson);build(rson);
        pup(rt);
    }
    void pdown(int rt,int left,int right)
    {
        if(lazy[rt])
        {
            int lt = lazy[rt];
            int mid = (left + right) >> 1;
            val[ls] += (mid - left + 1) * lt;
            val[rs] += (right - mid) * lt;
            lazy[rs] += lt;
            lazy[ls] += lt;
            lazy[rt] = 0;
        }
    }
    void updata(int rt,int left,int right,int l,int r,int k)
    {
        if(left > r || right < l)return;
        if(l <= left && right <= r)
        {
            val[rt] += (right - left + 1) * k;
            lazy[rt] += k;
            return;
        }
        pdown(rt,left,right);
    
        int mid = (left + right) >> 1;
    
        if(left <= mid)
            updata(lson,l,r,k);
        if(right > mid)
            updata(rson,l,r,k);
    }
    void updata_lca(int x,int y,int k)
    {
        while(top[x] != top[y])
        {
            if(dep[top[x]] < dep[top[y]])swap(x,y);
            updata(1,1,tot,num_id[top[x]],num_id[x],k);
            x = fa[top[x]];
        }
        if(dep[x] < dep[y])swap(x,y);
        updata(1,1,tot,num_id[y],num_id[x],k);
    }
    int query(int rt,int left,int right,int l,int r)
    {
        int res = 0;
        if(left > r || right < l)return 0;
    
        if(l <= left && right <= r)
        {
            return val[rt];
        }
    
        pdown(rt,left,right);
    
        int mid = (left + right) >> 1;
        if(left <= mid)res += query(lson,l,r);
        if(right > mid)res += query(rson,l,r);
    
        return res;
    }
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&p))
        {
            init();
            for(int i = 1;i <= n;++i)
            {
                scanf("%d",&V[i]);
            }
            int from,to;
            for(int i = 1;i <= m;++i)
            {
                scanf("%d%d",&from,&to);
                add(from,to);
                add(to,from);
            }
            dfs1(1,1,1);
            //忘记init
            dfs2(1,1);
            build(1,1,tot);
            //cout<<val[1]<<" "<<val[2]<<" "<<val[3]<<" "<<val[4]<<" "<<val[5]<<endl;正确建树
            char op[2];
            int x,y,z;
            for(int i = 0;i < p;++i)
            {
                scanf("%s",op);
                if(op[0] == 'I')
                {
                    scanf("%d%d%d",&x,&y,&z);
                    updata_lca(x,y,z);
                }
                else if(op[0] == 'D')
                {
                    scanf("%d%d%d",&x,&y,&z);
                    //cout<<num_id[x]<<" "<<num_id[y]<<endl;
                    updata_lca(x,y,-z);
                }
                else
                {
                    scanf("%d",&x);
                    //cout<<num_id[x]<<endl;对
                    printf("%d
    ",query(1,1,tot,num_id[x],num_id[x]));
                }
            }
        }
        return 0;
    }
    /*
    3 2 500
    1 2 3
    2 1
    2 3
    */
    
  • 相关阅读:
    我的访问量咋才3万了
    Khronos发布WebGL标准规范 1.0
    X3Dom V1.2发布
    解决Linux(Fedora Ubuntu)笔记本的待机休眠
    多用户虚拟Web3D环境Deep MatrixIP9 1.04发布
    网络科技公司Web开发团队管理的小结
    XamlReader 动态加载XAML
    Excel Data Reader开源的.NET excel读取库
    .net Sql server 事务的两种用法
    通过使用客户端证书调用 Web 服务进行身份验证{转}
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9582833.html
Copyright © 2011-2022 走看看