zoukankan      html  css  js  c++  java
  • 树链剖分-bzoj1036

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

      输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
    一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
    的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

      对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    http://www.hekai.site/wordpress/2017/06/24/%E8%AF%A6%E8%A7%A3%E6%A0%91%E9%93%BE%E5%89%96%E5%88%86/
    HK大佬的blog,一看就懂
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 30500
    using namespace std;
    int n,tot,lable,next[N<<1],head[N<<1],to[N<<1],a[N],fa[N],dep[N],son[N],size[N],tid[N],number[N];
    int top[N],Max[N*4],sum[N*4];
    bool visit[N];
    void make_way(int u,int v)
    {
        to[++tot]=v;
        next[tot]=head[u];
        head[u]=tot;
    }
    void dfs(int u,int depth,int father)
    {    
        visit[u]=1;fa[u]=father,dep[u]=depth,son[u]=0,size[u]=1;
        int maxsize=0;
        for(int edge=head[u];edge;edge=next[edge])
        {
            int v=to[edge];
            if(!visit[v])
            {
                dfs(v,depth+1,u);
                size[u]+=size[v];
                if(size[v]>maxsize)
                {
                    son[u]=v;maxsize=size[v];
                } 
            }
        }
    }
    void dfs1(int u,int ancestor)
    {
        visit[u]=1,tid[u]=++lable,number[lable]=u,top[u]=ancestor;
        if(son[u]!=0) dfs1(son[u],ancestor);
        for(int edge=head[u];edge;edge=next[edge])
        if(!visit[to[edge]])dfs1(to[edge],to[edge]);
    }
    void update(int u)
    {
        Max[u]=max(Max[u<<1],Max[u<<1|1]);
        sum[u]=sum[u<<1]+sum[u<<1|1];
    }
    void build(int u,int l,int r)
    {
        Max[u]=-1<<29,sum[u]=0;
        if(l==r)
        {
            Max[u]=sum[u]=a[number[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        update(u);
    }
    void change(int u,int l,int r,int x,int val)
    {
        if(l==r)
        {
            Max[u]=sum[u]=val;
            return;
        }
        int mid=(l+r)>>1;
        if(x<=mid) change(u<<1,l,mid,x,val);else change(u<<1|1,mid+1,r,x,val);
        update(u); 
    }
    int query(int u,int l,int r,int x,int y,int q)
    {
        //cout<<u<<' '<<l<<' '<<r<<' '<<x<<' '<<y<<' '<<q<<endl;
        //if(!u) return 0;
        if (x==l&&r==y) 
        {
            if (q==0) return Max[u];else return sum[u];
        }
        int mid=(l+r)>>1;
        if(x>mid) return query(u<<1|1,mid+1,r,x,y,q);else
            if(y<=mid) return query(u<<1,l,mid,x,y,q);else
            {
                if(q==0) return max(query(u<<1,l,mid,x,mid,q),query(u<<1|1,mid+1,r,mid+1,y,q));else
                 return    query(u<<1,l,mid,x,mid,q)+query(u<<1|1,mid+1,r,mid+1,y,q);
            }
    }
    int Query(int x,int y,int q)
    {
        int ans;
        if(q) ans=0;else ans=-1<<29;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            if(q==0) ans=max(ans,query(1,1,n,tid[top[x]],tid[x],0));
            else ans+=query(1,1,n,tid[top[x]],tid[x],1);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        if(q==0) ans=max(ans,query(1,1,n,tid[x],tid[y],0));else
        ans+=query(1,1,n,tid[x],tid[y],1);
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            make_way(x,y);
            make_way(y,x); 
            
        }
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        int m;
        scanf("%d",&m);
        memset(visit,0,sizeof(visit));
        dfs(1,1,0);
        memset(visit,0,sizeof(visit));
        dfs1(1,0);
        //cout<<n<<endl;
        build(1,1,n);
        char str[10];
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%s %d %d",str,&x,&y);
            if(str[0]=='C') change(1,1,n,tid[x],y);else
            if(str[1]=='M') printf("%d
    ",Query(x,y,0));else
            printf("%d
    ",Query(x,y,1));
        }
        return 0;
    }

    不过HK的线段树太玄妙,看不懂

  • 相关阅读:
    MQTT入门1 -- mosquitto 安装
    利用wireshark抓取TCP的整个过程分析。
    ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程
    移植ARM linux下远程连接工具dropbear
    飞凌2440开发板制作路由器
    基于视觉寻迹的寻路算法
    Linux I2C驱动架构
    Linux 设备树学习——基于i2c总线分析
    Linux SPI驱动学习——注册匹配
    从Linux内核LED驱动来理解字符设备驱动开发流程
  • 原文地址:https://www.cnblogs.com/dancer16/p/7411455.html
Copyright © 2011-2022 走看看