• HDU 1556 线段树或树状数组,插段求点


    1、HDU 1556  Color the ball   区间更新,单点查询

    2、题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次。

    (1)树状数组

    总结:树状数组是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值。

    这里改下思路可以用树状数组。在更新(a,b)时,向上更新,将a~n加1,b+1~n减1。查询点时,向下求和即可。

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #define F(i,a,b) for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b) memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define LL long long
    using namespace std;
    const int N=10010,MAX=100100;
    
    int n,c[MAX];
    
    int lowbit(int x) {
        //计算2^k
        return x&-x;
    }
    
    void update(int x,int val)
    {
        //向上更新,使所有包含了x的区间都更新一下
        while(x<=n) {
            c[x]+=val;
            x+=lowbit(x);
        }
    }
    
    int Sum(int x)
    {
        //向下查询
        int sum=0;
        while(x>0) {
            sum+=c[x];
            x-=lowbit(x);
        }
        return sum;
    }
    
    int main()
    {
        while(~scanf("%d",&n),n) {
            mes(c,0);
            int a,b;
            FF(i,1,n) {
                scanf("%d%d",&a,&b);
                update(a,1);
                update(b+1,-1);
            }
            F(i,1,n) printf("%d ",Sum(i));
            printf("%d
    ",Sum(n));
        }
    
        return 0;
    }
    View Code

     (2)线段树+lazy思想

    总结:lazy,更新时只到区间,可以节省很多时间。

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #define F(i,a,b) for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b) memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define LL long long
    using namespace std;
    const int N=10010,MAX=100010;
    
    int n,c[MAX<<2];
    
    void build(int o,int L,int R)
    {
        c[o]=0;
        if(L==R) return ;
        int mid=(L+R)>>1;
        build(o<<1,L,mid);
        build(o<<1|1,mid+1,R);
    }
    
    void update(int o,int l,int r,int L,int R)
    {
        if(l<=L&&R<=r) { c[o]++; return ; }     //关键:只更新到区间,一开始更新到每个单独的点,果断T了,//然后用l==L&&R==r,又果断MLE
        int mid=(L+R)>>1;
        if(mid<l) update(o<<1|1,l,r,mid+1,R);
        else if(r<=mid) update(o<<1,l,r,L,mid);
        else {
            update(o<<1,l,r,L,mid);
            update(o<<1|1,l,r,mid+1,R);
        }
    }
    
    int ans[MAX];
    void query(int o,int L,int R)
    {
        if(c[o]) {
            for(int i=L; i<=R; i++)
                ans[i]+=c[o];   //也是lazy思想,标记了的区间就加上
        }
        if(L==R) return ;   //询问时还是要到点
        int mid=(L+R)>>1;
        query(o<<1,L,mid);
        query(o<<1|1,mid+1,R);
    }
    
    int main()
    {
        while(~scanf("%d",&n) ,n )
        {
            build(1,1,n);
            fill(ans+1,ans+1+n,0);       //fil函数
            int a,b;
            FF(i,1,n) {
                scanf("%d%d",&a,&b);
                update(1,a,b,1,n);
            }
            query(1,1,n);
            F(i,1,n) printf("%d ",ans[i]);
            printf("%d
    ",ans[n]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Eclipse下Tomcat插件的安装
    Eclipse插件的安装方法
    tomcat 详解五 tomcat页面设置访问权限
    W3C XML Schema 教程
    vb.net向Excel中写入值
    用VB操作Excel的方法
    怎样用VB自动更新应用程序
    VB读写INI文件的四个函数以及相关API详细说明
    oracle数据库元数据SQL查询
    javascript JTimer_2.0 时间日历控件使用方法
  • 原文地址:https://www.cnblogs.com/sbfhy/p/6005338.html
Copyright © 2020-2023  润新知