HDU 4325 离散化 + 线段树

来源:互联网 发布:怎么查找淘宝评论过的 编辑:程序博客网 时间:2024/04/28 19:25

题意:

给出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;}