线段树+离散化

http://acm.hdu.edu.cn/showproblem.php?pid=4325

题意:

  有n种花每种开放的时间从a到b(a到b的闭区间),问t时刻有多少种花开着(n<=10^6,a<=b<10^9)

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 using namespace std;
 5 const int Ni = 1000010;
 6 struct node {
 7     int l,r,sum;
 8 }tree[Ni*3];
 9 struct node1{
10     int l,r;
11 }flo[Ni];
12 int x[Ni*2];
13 int n,m;
14 void build(int l,int r,int i)
15 {
16     tree[i].l=x[l];tree[i].r=x[r];
17     tree[i].sum=0;
18     if(l==r) return ;
19     int mid=(l+r)>>1;
20     build(l,mid,i<<1);
21     build(mid+1,r,i<<1|1);
22 }
23 void update(int l,int r,int i)
24 {
25     if(l<=tree[i].l&&tree[i].r<=r)
26         {tree[i].sum++;return;}
27 
28     if(r<=tree[i<<1].r) update(l,r,i<<1);
29     else if(l>=tree[i<<1|1].l) update(l,r,i<<1|1);
30     else
31     {
32         update(l,tree[i<<1].r,i<<1);
33         update(tree[i<<1|1].l,r,i<<1|1);
34     }
35 }
36 int qurey(int key,int i)
37 {
38     int ans=tree[i].sum;
39     if(tree[i].l==tree[i].r)//到叶子结点
40         return tree[i].sum;
41     if(key<=tree[i<<1].r)//在左子树
42         return ans+qurey(key,i<<1);
43     if(key>=tree[i<<1|1].l)//在右子树
44         return ans+qurey(key,i<<1|1);
45     int a=qurey(key,i<<1);//在中间
46     int b=qurey(key,i<<1|1);
47     ans+=min(a,b);
48     return ans;
49 }
50 int main()
51 {
52     int cs=1,i,t,q,num;
53     cin>>t;
54     for(cs=1;cs<=t;cs++)
55     {
56         cin>>n>>m;
57         for(num=i=0;i<n;i++)
58         {
59             scanf("%d%d",&flo[i].l,&flo[i].r);
60             x[num++]=flo[i].l;
61             x[num++]=flo[i].r;
62         }
63         sort(x,x+num);
64         num=(num-1)<<1;
65         for(i=num;i>=0;i-=2)//插点
66         {
67             x[i]=x[i>>1];
68             x[i-1]=(x[i>>1]+x[(i>>1)-1])>>1;
69         }
70         for(i=1,q=0;i<=num;i++)//缩点
71         {
72             if(x[q]!=x[i]) x[++q]=x[i];
73         }
74         build(0,num=q,1);//0到num的结点建树
75         for(i=0;i<n;i++)
76         {
77             update(flo[i].l,flo[i].r,1);
78         }
79         printf("Case #%d:\n",cs);
80         for(i=0;i<m;i++)
81         {
82             scanf("%d",&q);
83             if(q<x[0]||q>x[num]) printf("0\n");
84             else
85             printf("%d\n",qurey(q,1));
86         }
87     }
88     return 0;
89 }
90 /*
91 1
92 3 100
93 4 5
94 2 7
95 7 10
96 6
97 */

 

 

posted @ 2012-08-01 09:57  qijinbiao1  阅读(194)  评论(0编辑  收藏  举报