zoukankan      html  css  js  c++  java
  • hdu4325-Flowers-树状数组+离散化

    Flowers

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 3687    Accepted Submission(s): 1821


    Problem Description
    As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flowers will bloom in the garden in a specific time. But there are too many flowers in the garden, so he wants you to help him.
     
    Input
    The first line contains a single integer t (1 <= t <= 10), the number of test cases.
    For each case, the first line contains two integer N and M, where N (1 <= N <= 10^5) is the number of flowers, and M (1 <= M <= 10^5) is the query times. 
    In the next N lines, each line contains two integer Si and Ti (1 <= Si <= Ti <= 10^9), means i-th flower will be blooming at time [Si, Ti].
    In the next M lines, each line contains an integer Ti, means the time of i-th query.
     
    Output
    For each case, output the case number as shown and then print M lines. Each line contains an integer, meaning the number of blooming flowers.
    Sample outputs are available for more details.
     
    Sample Input
    2
    1 1
    5 10
    4
    2 3
    1 4
    4 8
    1
    4
    6
     
     
    Sample Output
    Case #1:
    0
    Case #2:
    1
    2
    1
     
    题意:有n朵花,每一朵花只会在固定的时间范围内绽放,m次询问,让你求在某个时刻有多少朵花是绽放的。
    思路:这题可以看成是树状数组的区间更新,给出每一朵花开放的时间范围,就相当于做一次区间更新,这个范围内的每个点加1,直接使用树状数组区间跟新的模板就好了。
    可是这题有个问题,那就是花开放范围的数据极大(1-10^9),无法直接开数组储存每一个点。那怎么办呢,很明显需要用到数据的离散化。
    我们可以发现,虽然花开放范围极大,但是总共只有n朵花,n最大是10^5,每一个范围由两个数l,r组成,再加上最多10^5个查询数,也就意味着一组数据最多出现3*(10^5)个不同的数据,数组完全能够存下。而且我们判断花是否在某一时刻开放,只需要知道数与数之间的相对大小,而不需要在意具体数值(某一时刻在 l , r之间,即花是开的),所以,这就满足了离散化的条件。
    我们对每一朵花开放的范围进行离散化,也对查询的时刻进行离散化,这样,就不会改变他们的相对大小。然后使用树状数组区间更新+单点查询即可。
    离散化的方法:将所有出现的数存入数组,去除重复出现的数,再进行排序,排序后这个数在数组中对应的下标,即为其离散化之后的数值。
     
    代码:
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<string>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<stack>
     8 #include<climits>
     9 #include<map>
    10 #include<queue>
    11 #define eps 1e-7
    12 #define ll long long
    13 #define inf 0x3f3f3f3f
    14 #define pi 3.141592653589793238462643383279
    15 using namespace std;
    16 const int MAXN = 3e5 + 21;
    17 
    18 int getNum[MAXN],li[MAXN/3],ri[MAXN/3],c[MAXN];
    19 
    20 int lowBit(int x)
    21 {
    22     return x&(-x);
    23 }
    24 
    25 void add(int x,int num,int len) //区间更新 
    26 {
    27     for(int i=x; i<=len; i+=lowBit(i))
    28     {
    29         c[i] += num;
    30     }
    31 }
    32 
    33 ll query(int x) //单点查询 
    34 {
    35     ll ans = 0;
    36     for(int i=x; i>0; i-=lowBit(i))
    37     {
    38         ans += c[i];
    39     }
    40     return ans;
    41 }
    42 
    43 int bSerach(int num,int len) //找出某个数在数组中的下标,并返回下标+1 
    44 {
    45     return lower_bound(getNum,getNum+len,num) - getNum + 1;
    46 }
    47 
    48 int main()
    49 {
    50     int t,n,m,cnt = 0;
    51     cin>>t;
    52     while(t--)
    53     {
    54         memset(c,0,sizeof(c));
    55         memset(getNum,0,sizeof(getNum));
    56     
    57         scanf("%d%d",&n,&m);
    58         
    59         int cnt1 = 0;
    60         
    61         for(int i=0; i<n; ++i)
    62         {
    63             scanf("%d%d",&li[i],&ri[i]);
    64             getNum[cnt1++] = li[i]; //将花开放范围出现的数据存入数组 
    65             getNum[cnt1++] = ri[i];
    66         }
    67         
    68         int ques[MAXN/3];
    69         for(int i=0; i<m; ++i)
    70         {
    71             scanf("%d",&ques[i]); 
    72             getNum[cnt1++] = ques[i]; //将查询出现的数据存入数组 
    73         }
    74         
    75         sort(getNum,getNum+cnt1); //给所有出现的数排序 
    76         
    77         int cnt2 = 1;
    78         for(int i=1; i<cnt1; ++i)
    79         {
    80             if(getNum[i] != getNum[i-1]) //去除重复的数 
    81                 getNum[cnt2++] = getNum[i];
    82         }
    83         
    84         
    85         for(int i=0; i<n; ++i) //树状数组区间更新
    86         {
    87             add( bSerach(li[i],cnt2), 1,cnt2);
    88             add( bSerach(ri[i],cnt2)+1, -1,cnt2);
    89         }
    90         
    91         printf("Case #%d:
    ",++cnt);
    92         for(int i=0; i<m; ++i)
    93         {
    94             cout<<query( bSerach(ques[i], cnt2) )<<endl; //树状数组单点查询 
    95         }
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    Atitit attilax要工作研究的要素 纪要 方案 趋势 方向 概念 理论
    Atitit 常见每日流程日程日常工作.docx v7 r8f
    Atitit it 互联网 软件牛人的博客列表
    Atitit 信息链(Information Chain)的概念理解 attilax总结
    Atitit 知识点的体系化 框架与方法 如何了解 看待xxx
    Atitit 聚合搜索多个微博 attilax总结
    Atitit 企业知识管理PKM与PIM
    Atitit 项目沟通管理 Atitit 沟通之道 attilax著.docx
    Atitit 项目管理软件 在线服务 attilax总结 1. 项目管理协作的历史 1 1.1. Worktile 406k 1 1.2. Teambition  584k in baidu
    Atitit.每周末总结 于每周一计划日程表 流程表 v8 import 上周遗漏日志补充 检查话费 检查流量情况 Crm问候 Crm表total and 问候
  • 原文地址:https://www.cnblogs.com/tuyang1129/p/9886070.html
Copyright © 2011-2022 走看看