【题解】hdu4325(2018-07-24校赛树状数组 A) 树状数组+离散化+二分

48 篇文章 0 订阅
23 篇文章 0 订阅
该博客分享了一道关于树状数组的算法题,通过离散化和二分查找来解决。博主详细介绍了如何将时间排序并进行离散化处理,同时在操作过程中采用手动去重和二分查找技术,以求解问题。
摘要由CSDN通过智能技术生成

题目链接
把时间排序后离散化再操作(又是手动去重手动二分查找)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int sum[N*2];
int q[N];//询问 
int n,m;
int maxn;//实际时间上限 
int st[N],ed[N];//起点终点 
int time[N*4];//时间线 
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int val)
{
    while(x<=maxn)
    {
        sum[x]+=val;
        x+=lowbit(x);
    }
}
void range_add(int l,int r,int val)
{
    add(l,val);add(r+1,-val);
}
int query(int x)
{
    int ret=0;
    while(x)
    {
        ret+=sum[x];
        x-=lowbit(x);
    }
    return ret;
}
int bs(int t,int r)//二分查找 
{
    r--;
    int l=0,mid;
    while(l<=r)
    {
        mid=l+r>>1;
        if(time[mid]==t)return mid;
        if(time[mid]<t)l=mid+1;
        else r=mid-1;
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int k,i,top;
    scanf("%d",&k);
    for(int ca=1;ca<=k;ca++)
    {
        top=0;
        memset(sum,0,sizeof(sum));
        memset(time,0,sizeof(time));
        printf("Case #%d:\n",ca);
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&st[i],&ed[i]);
            time[top++]=st[i];
            time[top++]=ed[i];
        }
        for(i=0;i<m;i++)
        {
            scanf("%d",&q[i]);
            time[top++]=q[i];
        }
        sort(time,time+top);
        int t=1;
        for(int i=1;i<top;i++)
        if(time[i]!=time[i-1])time[t++]=time[i];//去重 
        maxn=t+1;
        sort(time,time+t);
        for(int i=0;i<n;i++)
        {
            int l=bs(st[i],t);
            int r=bs(ed[i],t);
            range_add(l+1,r+1,1);
        }
        for(int i=0;i<m;i++)
        {
            int ask=bs(q[i],t);
            printf("%d\n",query(ask+1));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值