zoukankan      html  css  js  c++  java
  • 北京信息科技大学第十一届程序设计竞赛I:andy种树 (线段树 差分)

    https://ac.nowcoder.com/acm/contest/940/I
     

    题目描述

    andy在他的庄园里种了n棵树,排列成一排,标号为1到n。最开始的时候n棵树的高度都是0,也就是种子刚刚被埋下,树还没有长出来。

    andy会一种魔法,他每使用一次魔法,就可以让树标号落在连续区间[l, r]里的树的高度增加1。他可以使用q次这种魔法,然后他很好奇,在使用了q次魔法之后,他的所有树的高度分别是多少呢?

    输入描述:

    第一行输入两个整数n,q。(1<= n, q <= 1e5)
    
    接下来q行,每行输入两个整数l, r(l <= r),表示andy让标号落在区间[l, r]里的数高度都加1

    输出描述:

    输出有一行n个整数,每个整数后面有空格。输出末尾没有换行
    
    第i个数表示第i棵树的高度

    示例1

    输入

    复制

    10 3
    1 3
    2 4
    3 3

    输出

    复制

    1 2 3 1 0 0 0 0 0 0

    说明

    andy种了10棵树
    
    第一次使用魔法使得1、2、3棵树的高度增加1,
    
    所有树的高度为
    
    1 1 1 0 0 0 0 0 0 0
    
    第二次使用魔法使得2、3、4棵树的高度增加1,
    
    所有树的高度为
    
    1 2 2 1 0 0 0 0 0 0
    
    第三次使用魔法使得第3棵树的高度增加1
    
    所有树的高度为
    
    1 2 3 1 0 0 0 0 0 0

    解题思路:

    线段树区间修改模板。

    现在对线段树有一些了解,但是还是不太熟练。

    #include<bits/stdc++.h>
    using namespace std;
    int n, p, m, ans;
    struct node
    {
        int l,r,w,f;
    }tree[400001];
    void build(int k,int ll,int rr)
    {
        tree[k].l=ll,tree[k].r=rr;
        if(tree[k].l==tree[k].r)
        {
           	tree[k].w=0;
        	return;
        }
        int m=(ll+rr)/2;
        build(k*2,ll,m);
        build(k*2+1,m+1,rr);
    }
    void down(int k)
    {
        tree[k*2].f+=tree[k].f;
        tree[k*2+1].f+=tree[k].f;
        tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
        tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
        tree[k].f=0;
    }
    void change_interval(int k, int a, int b)
    {
        if(tree[k].l>=a&&tree[k].r<=b)
        {
            tree[k].w+=(tree[k].r-tree[k].l+1);
            tree[k].f+=1;
            return;
        }
        if(tree[k].f) down(k);
        int m=(tree[k].l+tree[k].r)/2;
        if(a<=m) change_interval(k*2, a, b);
        if(b>m) change_interval(k*2+1, a, b);
        tree[k].w=tree[k*2].w+tree[k*2+1].w;
    }
    
    void ask_point(int k, int x)
    {
        int m;
        if(tree[k].l==tree[k].r)
        {
            ans=tree[k].w;
            return ;
        }
        if(tree[k].f) down(k);
        m=(tree[k].l+tree[k].r)/2;
        if(x<=m) ask_point(k*2, x);
        else ask_point(k*2+1, x);
    }
    int main()
    {
        int i, a, b;
        scanf("%d",&n);
        build(1, 1, n); 
        scanf("%d",&m); 
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            change_interval(1, a, b);
        }
        for(i=1; i<=n; i++)
        {
        	ask_point(1,i);
        	printf("%d ", ans);
        }	
        return 0;
    }

    后来看了别人代码,这是一道差分裸题。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100020
    int a[N];
    int main()
    {
        int n, q, i, l, r;   
        scanf("%d%d", &n, &q);
        while(q--)
        {
            scanf("%d%d", &l, &r);
            a[l]++;
            a[r+1]--;
        }
        for(int i=1;i<=n;i++){
            a[i]+=a[i-1];
            printf("%d ", a[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    如何使用Arrays工具类操作数组
    Java 内存模型详解
    HashSet源码分析:JDK源码系列
    在ASP.NET Core中用HttpClient(六)——ASP.NET Core中使用HttpClientFactory
    在ASP.NET Core中用HttpClient(五)——通过CancellationToken取消HTTP请求
    在ASP.NET Core中用HttpClient(四)——提高性能和优化内存
    ASP.NET Core与Redis搭建一个简易分布式缓存
    在ASP.NET Core中用HttpClient(三)——发送HTTP PATCH请求
    在ASP.NET Core中用HttpClient(二)——发送POST, PUT和DELETE请求
    在ASP.NET Core中用HttpClient(一)——获取数据和内容
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852640.html
Copyright © 2011-2022 走看看