• 牧草种植


    农民约翰有N个贫瘠的牧场(2 <= N <= 100,000),由N-1条双向道路连接,因此在任何两个牧场之间只有一条路径。贝西是一位喜欢吃草时间的奶牛,他经常抱怨牧场间道路上没有草。农夫约翰非常喜欢贝西,今天他终于在道路上种草了。他将使用由M个步骤组成的程序(1 <= M <= 100,000)。

    在每一步都会发生以下两件事之一:

    • FJ会选择两个牧场,在两个牧场之间的每条道路上种上一块草地,或者,

    • 贝西会询问某条路上有多少块草地,而农民约翰必须回答她的问题。

    农夫约翰是一个非常贫穷的柜台 - 帮助他回答贝西的问题!

    给出一棵Ñ个节点的树,有米个操作,操作为将一条路径上的边权加一或询问某条边的权值。

    输入输出格式

    输入格式:

    *第1行:两个空格分隔的整数N和M.

    *第2..N行:两个空格分隔的整数,用于描述道路的端点。

    *第N + 1..N + M行:第i + 1行描述第i步。该行的第一个字符是P或Q,它描述了FJ是种草还是简单查询。其后是两个空格分隔的整数A_i和B_i(1 <= A_i,B_i <= N),它们描述了FJ的动作或查询。

    输出格式:

    *第1行.. ???:每行都有查询的答案,与查询出现在输入中的顺序相同。

    输入输出样例

    输入样例#1: 复制
    4 6 
    1 4 
    2 4 
    3 4 
    P 2 3 
    P 1 3 
    Q 3 4 
    P 1 4 
    问2 4 
    Q 1 4 
    
    输出样例#1: 复制
    2 
    1 
    2 
    

    题 解

      首先不要在意翻译了。。。。

      这是一个好题,关于树链剖分的边转点

      我们要怎么实现边转点呢?

      可以这么想,因为每两个点之间都只有一个边相连,我们可以考虑把值赋给深度深的,这样的询问的话,我们就只要在最后不计算lca的值就ok了


    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=500001;
    int head[N],fa[N],dep[N];
    struct node{
        int to,next;
    }e[N];
    int ch[N],sum[N],a[N],l[N],top[N],lazy[N];
    int size[N],son[N];
    
    void build(int root,int l,int r)
    {
        int mid=l+r>>1;
        if(l==r)
        {
            sum[root]=a[l];
            //cout<<a[l]<<' '<<l<<endl;
            return ;
        }
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        sum[root]=sum[root<<1]+sum[root<<1|1];
        return ;
    }
    
    void push(int root,int l,int r)
    {
        int mid=l+r>>1;
        lazy[root<<1]+=lazy[root];
        lazy[root<<1|1]+=lazy[root];
        sum[root<<1|1]+=lazy[root]*(r-mid);
        sum[root<<1]+=lazy[root]*(mid-l+1);
        lazy[root]=0;
        return ;
    }
    
    void update(int root,int left,int right,int l,int r,int k)
    {
    
        if(l<=left&&r>=right)
        {
            sum[root]+=k*(right-left+1);
            lazy[root]+=k;
            return ;
        }
        if(l>right||r<left)return ;
        int mid=left+right>>1;
        if(lazy[root])push(root,left,right);
        if(mid>=l) update(root<<1,left,mid,l,r,k);
        if(mid<r)  update(root<<1|1,mid+1,right,l,r,k);
        sum[root]=sum[root<<1]+sum[root<<1|1];
        return ;
    }
    
    int query(int root,int left,int right,int l,int r)
    {
        if(l<=left&&r>=right)
        {
            return sum[root];
        }
        if(l>right||r<left)return 0;
        int mid=left+right>>1;
        if(lazy[root])push(root,left,right);
        int a=0,b=0;
        if(mid>=l) a=query(root<<1,left,mid,l,r);
        if(mid<r)  b=query(root<<1|1,mid+1,right,l,r);
        return a+b;    
    }
    
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!dep[v])
            {
                dep[v]=dep[x]+1;
                fa[v]=x;
                dfs1(v);
                size[x]+=size[v];
                if(size[v]>size[son[x]])son[x]=v;
            }
        }
        return;
    }
    int tot=0;
    void dfs2(int x,int t)
    {
        l[x]=++tot;a[tot]=ch[x];top[x]=t;
        if(son[x])dfs2(son[x],t);
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=fa[x]&&v!=son[x])
            dfs2(v,v);
        }
        return ;
    }
    int num=0;
    void add(int from,int to)
    {
        num++;
        e[num].to=to;
        e[num].next=head[from];
        head[from]=num;
    }
    
    void cap1(int x,int y)
    {
        int fy=top[y],fx=top[x];
        while(fy!=fx)
        {
            if(dep[fx]<dep[fy])
            {
                swap(fx,fy);swap(x,y);
            }
            update(1,1,tot,l[fx],l[x],1);
            x=fa[fx];
            fx=top[x];
        }
        if(l[x]>l[y])
        swap(x,y);
        update(1,1,tot,l[son[x]],l[y],1);
        return ;    
    }
    
    int  cap2(int x,int y)
    {
        int maxx=0;
        int fy=top[y],fx=top[x];
        while(fy!=fx)
        {
            if(dep[fx]<dep[fy])
            {
                swap(fx,fy);swap(x,y);
            }
            maxx+=query(1,1,tot,l[fx],l[x]);
            x=fa[fx];
            fx=top[x];
        }
        if(l[x]>l[y])
        swap(x,y);
        maxx+=query(1,1,tot,l[son[x]],l[y]);
        return maxx;
    }
    
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    int main()
    {
        int  n,m;
        n=read();m=read();
        for(int i=1;i<n;i++)
        {
            int x,y;
            x=read();y=read();
            add(x,y);add(y,x);
        }
        fa[1]=1;
        dep[1]=1;
        dfs1(1);
        
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            char qwq;
            cin>>qwq;
            if(qwq=='P')
            {
                int x,y;
                x=read();y=read();
                cap1(x,y);
            }
            else 
            {
                int x,y;
                x=read();y=read();
                printf("%d
    ",cap2(x,y));
            }
        }
        return 0;
    }
  • 相关阅读:
    英文字典。怎样设计数据结构
    最近看的几部电影电视剧
    pylucene 中文
    提高浏览体验的五十个最佳FireFox扩展插件
    结构和细节
    <传> 《程序猿装B指南》,程序员童鞋们请认真学习
    c++ builder TTreeView customSort 实现 自定义排序
    《转》c++ 字符串系列:字符编码进阶(下)
    庆祝我又读完一本书
    c++ 回调函数深究
  • 原文地址:https://www.cnblogs.com/hhh1109/p/8780716.html
Copyright © 2020-2023  润新知