【数字_ID】HDU-1556-Color the ball(树状数组/区间修改单点查询)

  • 编辑:数字_ID
  • 2018年5月21日

1. 写在题前

  • 树状数组很优雅,所以就找了一道水题来找信心
  • 尽量日更或者隔日更吧,之前比赛没更,所以今天补上

2. 题意

  • 有n个数,,k次操作,每次操作对某个区间的所有数都+1,问第i个数最后变成了多少

3. 关于树状数组

  • 非常优雅
  • 数组里每个位置存的数,是这个位置坐标所管理的范围的数的和,每个坐标所管理的范围,是从这个数开始往前数2^k个,其中k是这个坐标二进制末尾0的个数
  • 网上有很多教程,大家可以学习学习,在这里放出炒鸡经典的一个图
    树状数组.png

4. 关于这道题

  • 这道题有一个很有意思的地方,一般树状数组是求前缀和的,但通过某种操作,可以用来求单个点的值,这种操作使得区间修改的复杂度大大降低
  • 首先来看题目,是要对某个区间进行加固定值的操作,对于树状数组,每改变一个值,就要进行O(logn)的复杂度来修改某些前缀和,对于n个点,复杂度就变成了O(nlogn)。然而这道题有这么一种更简单的做法,对(i,j)区间进行每个数加一个v,只需要对第i个位置加v,对第j+1个数-v,这样每个位置的前缀和就是该位置最终的数,非常的巧妙,大家可以自己思索一些,很优雅

5. 代码

#include<string.h>
#include<stdio.h>
#include<iostream>

using namespace std;


#define lowbit(x) (x&(-x))
const int maxn = 100020;

int n;
int a,b;
int sum[maxn];
void add(int pos,int val)
{
    while(pos<=n)
    {
        sum[pos] += val;
        pos += lowbit(pos);
    }
}

int query(int pos)
{
    int res = 0;
    while(pos>0)
    {
        res += sum[pos];
        pos -= lowbit(pos);
    }
    return res;
}
int main()
{
    while(cin>>n&&n!=0)
    {
        memset(sum,0,sizeof(sum));
        for(int i = 0;i<n;i++)
        {
            cin>>a>>b;
            add(a,1);
            add(b+1,-1);
        }
        for(int i = 1;i<=n;i++)
        {
            if(i == 1)cout<<query(i);
            else cout<<" "<<query(i);
        }
        cout<<endl;
    } 
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 树状数组用来求区间元素和,求一次区间元素和的时间效率为O(logn)。特别用于在数组内的参数变换后,再次求和所使用...
    碧影江白阅读 4,162评论 1 1
  • 《程序员代码面试指南-左程云》笔记 第一章 栈和队列 设计一个有getMin功能的栈 实现一个特殊的栈,在实现栈的...
    xiaogmail阅读 18,536评论 2 19
  • 3-20。118Days。 太久没有写日记了。 和能宝在被窝里玩到中午。梁先生今天又去医院替婆婆照顾外婆了,忘带充...
    林培阅读 2,784评论 0 0
  • NPM是随同Node.js一起安装的包管理工具,能解决Node.js代码部署上的很多问题。 所以先确保你正确安装了...
    Llane00阅读 5,697评论 0 1
  • 在朋友那儿听说 知心的你曾回来过 想请他替我向你问候 只为了怕见了说不出口 你对以往的感触还多不多 曾让我心碎的你...
    曾小莹阅读 4,340评论 0 1