HDU 4325 离散化 + 线段树

题意:

给出n个区间,【s,t】,区间,代表这个时间段有一朵花。

m个询问,每次询问一个时间点,输出该时间的花的数量。

思路:n <= 10W, m <= 10W 。

直接离散化之后然后线段树成段更新,输出点的值即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2005
#define inf 2000000000
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
using namespace std;

struct kdq
{
    int l,r;
    long long num , add;
} tree[1111111];

int n , m , t ;
long long ans;

void build_tree(int l,int r,int u)
{
    tree[u].l=l,tree[u].r=r;
    tree[u].add=0;
    if(l==r)
    {
        tree[u].num = 0 ;
        return ;
    }
    int mid=(l+r)/2;
    build_tree(l,mid,u<<1);
    build_tree(mid+1,r,(u<<1)+1);
    tree[u].num=tree[u<<1].num + tree[(u<<1)+1].num;
}
void query(int left,int right,int u)
{
    if(left>tree[u].r||right<tree[u].l)
    {
        return ;
    }
    if(left<=tree[u].l&&right>=tree[u].r)
    {
        ans+=tree[u].num;
        return ;
    }
    if(tree[u].add)
    {
        tree[u<<1].num += (tree[u<<1].r-tree[u<<1].l+1)*tree[u].add;
        tree[u<<1].add += tree[u].add;
        tree[(u<<1)+1].num += (tree[(u<<1)+1].r-tree[(u<<1)+1].l+1)*tree[u].add;
        tree[(u<<1)+1].add += tree[u].add;
        tree[u].add = 0;
    }
    query(left,right,u<<1);
    query(left,right,(u<<1)+1);
    tree[u].num=tree[u<<1].num+tree[(u<<1)+1].num;
}
void updata(int left,int right,int u,int k)
{
    if(left>tree[u].r||right<tree[u].l)
    {
        return ;
    }
    if(left<=tree[u].l&&right>=tree[u].r)
    {
        tree[u].num+=(tree[u].r-tree[u].l+1)*k;
        tree[u].add+=k;
        return ;
    }
    if(tree[u].add)
    {
        tree[u<<1].num += (tree[u<<1].r-tree[u<<1].l+1)*tree[u].add;
        tree[u<<1].add += tree[u].add;
        tree[(u<<1)+1].num += (tree[(u<<1)+1].r-tree[(u<<1)+1].l+1)*tree[u].add;
        tree[(u<<1)+1].add += tree[u].add;
        tree[u].add = 0;
    }
    updata(left,right,u<<1,k);
    updata(left,right,(u<<1)+1,k);
    tree[u].num=tree[u<<1].num+tree[(u<<1)+1].num;
}
struct road
{
    int x ,y ;
}a[100005] ;
int b[1000005] ;
int c[1000005] ;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("acm.txt", "r", stdin);
#endif
    cin >> t ;
    int ca = 0 ;
    while( t -- )
    {
        cin >> n >> m ;
        int dnum = 0 ;
        for (int i = 0 ;i < n ;i ++ )
        {
            scanf("%d%d",&a[i].x ,&a[i].y) ;
            b[dnum ++ ] = a[i].x ;
            b[dnum ++ ] = a[i].y ;
        }
        for (int i = 0 ;i < m ;i ++ )
        {
            scanf("%d",&c[i]) ;
            b[dnum ++ ] = c[i] ;
        }
        sort(b, b + dnum ) ;
        int nn = unique(b,b + dnum) - b ;
        build_tree(1,nn,1) ;
        printf("Case #%d:\n",++ca) ;
        for (int i = 0 ;i < n ;i ++ )
        {
            int ss = lower_bound(b,b + nn ,a[i].x) - b + 1 ;
            int tt = lower_bound(b, b + nn ,a[i].y) - b + 1 ;
            updata(ss, tt,1,1) ;
        }
        for (int i = 0 ;i < m ;i ++ )
        {
            ans = 0 ;
            int dd = lower_bound(b, b + nn ,c[i]) - b + 1 ;
            query(dd,dd,1) ;
            printf("%lld\n",ans) ;
        }
    }
    return 0;
}

显然用树状数组区间更新单点查询更快,更好写

int n , m ,nn ,D[N] ,X[N] , Y[N] ,Q[N] ,c[N] ;
int lowbit(int x){return x & (-x) ;}
void update(int x , int y){
    for (int i = x ; i >= 1 ; i -= lowbit(i))c[i] += y ;
}
int query(int x){
    int ans = 0 ;
    for (int i = x ; i <= nn ; i += lowbit(i))ans += c[i] ;
    return ans ;
}
void solve(){
    mem(c , 0) ;
    cin >> n >> m ;int num = 0 ;
    for (int i = 0 ; i < n ; i ++ ){
        RD(X[i]) ; RD(Y[i]) ;D[num ++ ] = X[i] ;
        D[num ++ ] = Y[i] ;
    }
    for (int i = 0 ; i < m ; i ++ ){
        RD(Q[i]) ; D[num ++ ] = Q[i] ;
    }
    sort(D , D + num) ;
    int k = unique(D , D + num ) - D ;
    nn = k ;
    for (int i = 0 ; i < n ; i ++ ){
        int x = lower_bound(D, D + k , X[i]) - D + 1 ;
        int y = lower_bound(D ,D + k , Y[i]) - D + 1 ;
        update(x - 1 , -1) ;
        update(y , 1) ;
    }
    for (int i = 0 ; i < m ; i ++ ){
        printf("%d\n",query(lower_bound(D, D + k , Q[i]) - D + 1)) ;
    }
}
int main() {
    int _ ;int ca = 0 ; cin >> _ ; while(_ -- )printf("Case #%d:\n",++ ca) ,solve() ;
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值