hdu4325树状数组,线段树,离散化

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4325
大意:本题就是求在某个时间点上开花的朵数
思路:此题后台测试数据很水,题目给的范围很大,但测试数据并没有他给的这么多,区间处理,树状数组,离散化都能解
1.离散化思想:https://blog.csdn.net/xiangaccepted/article/details/73276826
2.线段树思想:https://www.cnblogs.com/wuwangchuxin0924/p/5971849.html
3.树状数组思想(线段树的一种):https://www.cnblogs.com/wuwangchuxin0924/p/5921130.html
树状数组:
思路:假设更新区间(a,b),从a到b每一个点都要加上一朵,基于树状数组特殊结构,这里是假设从a点开始更新,树状数组会从a点一直加到n点,所以区间更新(a,b)区间只更新a点不用一个一个点去加,为了不影响后面的点的更新要减去多余增加的点update(b+1,-1);然后求sum(x);
1.树状数组

#include<cstdio>
#include<cstring>
#define len 100005 
using namespace std;
int n,c[len],ans[len];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int p)//单点更新 
{
    for(int i=x;i<=len;i=i+lowbit(i)) c[i]+=p;
}
int sum(int x)//起点到x点的和 
{
    int t=0;
    for(int i=x;i>0;i=i-lowbit(i)) t+=c[i];
    return t;
}
int main()
{
    int t,m,q,count=0;
    scanf("%d",&t);
    while(t--)
    {
        int a,b;
        memset(c,0,sizeof(c));
        memset(ans,0,sizeof(0));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            update(a,1);
            update(b+1,-1);
        }   
        for(int i=0;i<m;i++)
        {
            scanf("%d",&q);
            ans[i]=sum(q);
        }
        printf("Case #%d:\n",++count);
        for(int i=0;i<m;i++) printf("%d\n",ans[i]);
    }
    return 0;
}

2.树状数组+离散化1

#include<cstdio>
#include<cstring>
#include<algorithm>
#define len 100005 
using namespace std;
int n,c[len],ans[len],v[len];
struct node
{
    int x,y;
}s[len];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int p)
{
    for(int i=x;i<=len;i=i+lowbit(i)) c[i]+=p;
}
int sum(int x)
{
    int t=0;
    for(int i=x;i>0;i=i-lowbit(i)) t+=c[i];
    return t;
}
int main()
{
    int t,m,q,count=0;
    scanf("%d",&t);
    while(t--)
    {
        int k=0,h[len];
        memset(c,0,sizeof(c));
        memset(h,0,sizeof(0));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&s[i].x,&s[i].y);
            v[k++]=s[i].x;
            v[k++]=s[i].y;
        }
        for(int i=0;i<m;i++) scanf("%d",&h[i]),v[k++]=h[i];
        sort(v,v+k);
        int p=unique(v,v+k)-v;
        for(int i=0;i<n;i++)
        {
            int x=lower_bound(v,v+p,s[i].x)-v+1;
            int y=lower_bound(v,v+p,s[i].y)-v+1;
            update(x,1);
            update(y+1,-1);
        }
        printf("Case #%d:\n",++count);
        for(int i=0;i<m;i++)
        {
             int j=lower_bound(v,v+p,h[i])-v+1;
             printf("%d\n",sum(j));
        }
    }
    return 0;
}

2.树状数组+离散化2

#include<cstdio>
#include<cstring>
#include<algorithm>
#define len 100005 
using namespace std;
int n,c[len],ank[len*2];
struct node
{
    int i,x;
    bool operator <(const node &other)const
    {
        return x<other.x;
    }
}s[len];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int p)
{
    for(int i=x;i<=len;i=i+lowbit(i)) c[i]+=p;
}
int sum(int x)
{
    int t=0;
    for(int i=x;i>0;i=i-lowbit(i)) t+=c[i];
    return t;
}
int main()
{
    int t,m,count=0;
    scanf("%d",&t);
    while(t--)
    {
        memset(c,0,sizeof(c));
        memset(ank,0,sizeof(ank));
        scanf("%d%d",&n,&m);
        n=n*2;
        int h=m+n;
        for(int i=0;i<h;i++)
        {
            scanf("%d",&s[i].x);
            s[i].i=i;
        } 
        sort(s,s+h);
        int k=1;
        ank[s[0].i]=k;
        for(int i=1;i<h;i++)
        {
            if(s[i].x==s[i-1].x) ank[s[i].i]=k;
            else ank[s[i].i]=++k;
         } 
        for(int i=0;i<n-1;i+=2)
        {
            update(ank[i],1);
            update(ank[i+1]+1,-1);
        }
        printf("Case #%d:\n",++count);
        for(int i=n;i<h;i++) printf("%d\n",sum(ank[i]));
    }
    return 0;
}

3.线段树

#include<cstdio>
#include<algorithm>
#include<cstring>
#define len 100005 
using namespace std;
struct node
{
    int l,r,sum;
}s[len*4];
struct test
{
    int a,b;
}t[len];
int m,n,ans[len];
void pushup(int i)
{
    if(s[i].l==s[i].r) return ;
    if(s[i].sum)
    {
        s[i*2].sum+=s[i].sum;
        s[i*2+1].sum+=s[i].sum;
        s[i].sum=0;
    }
}
void build(int l,int r,int i)
{
    s[i].l=l;
    s[i].r=r;
    s[i].sum=0;
    if(s[i].l==s[i].r) return ;
    int mid=(s[i].l+s[i].r)/2;
    build(l,mid,i*2);
    build(mid+1,r,i*2+1);
}
void update(int l,int r,int i)
{
    if(s[i].l==l&&s[i].r==r) 
    {
        s[i].sum++;
        return ;
    }
    int mid=(s[i].l+s[i].r)/2;
    if(mid>=r) update(l,r,i*2);
    else if(mid<l) update(l,r,i*2+1);
    else
    {
        update(l,mid,i*2);
        update(mid+1,r,i*2+1);
    }
}
void query(int i)
{
    pushup(i); 
    if(s[i].l==s[i].r)
    {
       ans[s[i].l]=s[i].sum;
       return ;
    } 
    query(i*2);
    query(i*2+1);
}
int main()
{
    int count=0,p,h;
    scanf("%d",&h);
    while(h--)
    {
        int Max=-1;
        memset(ans,0,sizeof(ans));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&t[i].a,&t[i].b);
            Max=max(max(t[i].a,t[i].b),Max);
        }   
        build(1,Max,1);
        for(int i=1;i<=n;i++) update(t[i].a,t[i].b,1);
        query(1);
        printf("Case #%d:\n",++count);
        for(int i=0;i<m;i++)
        {
            scanf("%d",&p);
            printf("%d\n",ans[p]);
        } 
    }
    return 0;
}

4.线段树+离散化

#include<cstdio>
#include<algorithm>
#include<cstring>
#define len 100005 
using namespace std;
struct node
{
    int l,r,sum;
}s[len*4];
struct test
{
    int x,i;
    bool operator <(const test &other)const
    {
        return x<other.x;
    }
}t[len];
int m,n,k,ans[len],v[len];
void pushup(int i)
{
    if(s[i].l==s[i].r) return ;
    if(s[i].sum)
    {
        s[i*2].sum+=s[i].sum;
        s[i*2+1].sum+=s[i].sum;
        s[i].sum=0;
    }
}
void build(int l,int r,int i)
{
    s[i].l=l;
    s[i].r=r;
    s[i].sum=0;
    if(s[i].l==s[i].r) return ;
    int mid=(s[i].l+s[i].r)/2;
    build(l,mid,i*2);
    build(mid+1,r,i*2+1);
}
void update(int l,int r,int i)
{
    if(s[i].l==l&&s[i].r==r) 
    {
        s[i].sum++;
        return ;
    }
    int mid=(s[i].l+s[i].r)/2;
    if(mid>=r) update(l,r,i*2);
    else if(mid<l) update(l,r,i*2+1);
    else
    {
        update(l,mid,i*2);
        update(mid+1,r,i*2+1);
    }
}
void query(int i)
{
    pushup(i); 
    if(s[i].l==s[i].r)
    {
       ans[s[i].l]=s[i].sum;
       return ;
    } 
    query(i*2);
    query(i*2+1);
}
int main()
{
    int count=0,h;
    scanf("%d",&h);
    while(h--)
    {
        int Max=-1;
        memset(ans,0,sizeof(ans));
        scanf("%d%d",&n,&m);
        n=n*2;
        m+=n; 
        for(int i=0;i<m;i++)
        {
            scanf("%d",&t[i].x);
            t[i].i=i;
            Max=max(t[i].x,Max);
        }   
        build(1,Max,1);
        sort(t,t+m);
        k=1;
        v[t[0].i]=k;
        for(int i=1;i<m;i++)
        {
            if(t[i].x==t[i-1].x) v[t[i].i]=k;
            else v[t[i].i]=++k;
        }
        for(int i=0;i<n-1;i+=2) update(v[i],v[i+1],1);
        query(1);
        printf("Case #%d:\n",++count);
        for(int i=n;i<m;i++) printf("%d\n",ans[v[i]]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值