zoukankan      html  css  js  c++  java
  • nyoj 600——花儿朵朵——【离散化、线段树插线问点】

    花儿朵朵

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:5
     
    描述
    春天到了,花儿朵朵盛开,hrdv是一座大花园的主人,在他的花园里种着许多种鲜花,每当这个时候,就会有一大群游客来他的花园欣赏漂亮的花朵,游客们总是会询问,某个时间有多少种花儿同时在盛开着?hrdv虽然知道每种花儿的开花时间段,但是他不能很快的答出游客的问题,你能编写一个程序帮助他吗?
     
    输入
    第一行有个整数t,表示有t组测试数据,每组测试数据第一行为两个整数n,m(0<n<100000,0<m<100000);随后有n行,每一行有两个整数x,y(0<x<y<1000000000),表示这一种花的盛开时间是从x到y;随后有m行,每行有一个整数,代表游客询问的时间。
    输出
    对于每次游客的询问,输出一个整数在单独的一行,表示这个时间盛开的花有多少种。
    样例输入
    2
    1 1
    5 10
    4
    2 3
    1 4
    4 8
    1
    4
    6
    样例输出
    0
    1
    2
    1


    解题思路:先把所给的值都离散化后再操作。然后就是插线问点了。


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=120000;
    #define mid (L+R)/2
    #define lson rt*2,L,mid
    #define rson rt*2+1,mid+1,R
    int a[maxn*2],aa[maxn*2],a_[maxn*2];
    int x[maxn*2],y[maxn*2],q[maxn];
    int f_num[maxn*4];
    int discretization(int *tm,int l,int r,int key){
        int m;      //离散化
        while(l<=r){
            m=(l+r)/2;
            if(tm[m]<key){
                l=m+1;
            }else if(tm[m]>key){
                r=m-1;
            }else{
                return m;
            }
        }
    }
    void update(int rt,int L,int R,int l_ran,int r_ran){
        if(l_ran<=L&&R<=r_ran){ //区间更新
            f_num[rt]+=1;
            return ;
        }
        if(l_ran<=mid){
            update(lson,l_ran,r_ran);
        }
        if(r_ran>mid){
            update(rson,l_ran,r_ran);
        }
    }
    void PushDown(int rt){
        f_num[rt*2]+=f_num[rt];
        f_num[rt*2+1]+=f_num[rt];
        f_num[rt]=0;
    }
    int query(int rt,int L,int R,int v){    //单点查询
        if(L==R){   
            return f_num[rt];
        }
        if(f_num[rt]!=0)
        PushDown(rt);
        if(mid>=v){
            return query(lson,v);
        }
        if(mid<v){
            return query(rson,v);
        }
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            memset(f_num,0,sizeof(f_num));
            int n,m,tmp;
            scanf("%d%d",&n,&m);
            int num_a=n*2+m;
            for(int i=0;i<num_a;i++){
                scanf("%d",&tmp);
                a[i]=tmp;
                aa[i]=tmp;
            }
            sort(a,a+num_a);
            int num=0;
            a_[num++]=a[0];
            for(int i=1;i<num_a;i++){
                if(a[i]!=a[i-1]){
                    a_[num++]=a[i];
                }
            }
            int num_x=0,num_y=0,num_q=0,nn=0;
            for(int i=0;i<n*2;i++){
                if(i%2==0){
                    x[num_x++]=discretization(a_,0,num-1,aa[i])+1;
                    if(nn<x[num_x-1]){
                        nn=x[num_x-1];
                    }
                }else{
                    y[num_y++]=discretization(a_,0,num-1,aa[i])+1;
                    if(nn<y[num_y-1]){
                        nn=y[num_y-1];
                    }
                }
            }
            for(int i=n*2;i<num_a;i++){
                q[num_q++]=discretization(a_,0,num-1,aa[i])+1;
            }
            for(int i=0;i<n;i++){
                update(1,1,nn,x[i],y[i]);
            }
            for(int i=0;i<num_q;i++){
                int ans=query(1,1,nn,q[i]);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    谈谈我对服务熔断、服务降级的理解
    PS-AXI-GPIO-流水灯设计
    立创EDA的使用
    multisim的操作回顾
    verilog的文件流和项目流
    AXI4的主从机的收发机制
    AXI4协议的物理模型
    verilog中的数据类型
    matlab的基本操作
    ARM之AXI总线协议初试
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4470744.html
Copyright © 2011-2022 走看看