题目:给定很多花的开花时间段,询问某一时间点有多少朵花儿开放。
分析:线段树、离散化。利通每朵花的开花时间段的端点值将时间轴分割成区间段,则操作以每个区间段为整体进行。分割又两种方案:1.端点各成一段,端点间各成一段;2.建立左闭右开的区间,每个区间从上一个顶点开始、到下一个顶点之前结束(开区间)。本题采用方案2,方案一需要生成4倍花儿的数量,而方案2只需要2倍花儿的数量,空间复杂度会降低一倍。注意,在每个叶子节点上建立节点[a,a],因为操作[a,b]区间需要操作[a,b)和[b,b]两个区间,所以线段树的结点数是区间的3倍(2n-1+n),而不是通常的2倍(2n-1)。
注意:在线段树的建树过程中不要使用memset,会TLE。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int x[100005];
int y[100005];
int z[200005];
int s[200005];
typedef struct Tnode
{
Tnode* Lchild;
Tnode* Rchild;
int Lvalue;
int Rvalue;
int Counts;
}STnode;
STnode Node[600005];
class Stree
{
private:
STnode* Root;
int Count;
STnode* madetree( int a, int b ) {
STnode* np = &Node[Count++];
np->Counts = 0;
np->Lvalue = a;
np->Rvalue = b;
if ( a < b ) {
np->Lchild = madetree( a, (a+b)/2 );
if ( a+1 < b )
np->Rchild = madetree( (a+b)/2, b );
}else np->Lchild = np->Rchild = NULL;
return np;
}
public:
Stree( int a, int b ) {
Count = 0;
Root = madetree( a, b );
}
void Insert( STnode* r, int a, int b ) {
//printf("[%d %d] <%d %d>\n",r->Lvalue,r->Rvalue,a,b);
if ( r->Lvalue == a && r->Rvalue == b ) {
r->Counts ++;
return;
}
int mid = (r->Lvalue+r->Rvalue)>>1;
if ( b < mid || a == b ) {
if ( r->Lchild ) Insert( r->Lchild, a, b );
}else if ( a >= mid ) {
if ( r->Rchild ) Insert( r->Rchild, a, b );
}else {
if ( r->Lchild ) Insert( r->Lchild, a, mid );
if ( r->Rchild ) Insert( r->Rchild, mid, b );
}
}
int Query( STnode* r, int v ) {
if ( !r ) return 0;
//printf("{%d %d}\n",r->Lvalue,r->Rvalue);
if ( r->Lvalue == r->Rvalue )
return s[r->Lvalue]==v?r->Counts:0;
if ( v < s[r->Lvalue] || v >= s[r->Rvalue] )
return 0;
int mid = (r->Lvalue+r->Rvalue)>>1;
if ( v < s[mid] || r->Lvalue+1 == r->Rvalue )
return Query( r->Lchild, v )+r->Counts;
else
return Query( r->Rchild, v )+r->Counts;
}
void Insert( int a, int b ) {Insert( Root, a, b );}
int Query( int v ) {Query( Root, v );}
};
int Map( int numb, int m )
{
int l = 1,r = m,mid;
while ( l < r ) {
mid = (l+r)>>1;
if ( s[mid] < numb )
l = mid+1;
else r = mid;
}
return r;
}
int cmp( const void* a, const void* b )
{
return *((int *)a) - *((int*)b);
}
int main()
{
int n,m,t,a,b,ans;
while ( scanf("%d",&t) != EOF )
while ( t -- ) {
scanf("%d%d",&n,&m);
for ( int i = 0 ; i < n ; ++ i ) {
scanf("%d%d",&x[i],&y[i]);
z[i] = x[i];z[i+n] = y[i];
}
qsort( z, 2*n, sizeof( int ), cmp );
int count = 0;
s[++count] = z[0];
for ( int i = 1 ; i < 2*n ; ++ i )
if ( z[i-1] != z[i] )
s[++count] = z[i];
s[++count] = s[count-1]+1;
Stree ST( 1, count );
for ( int i = 0 ; i < n ; ++ i ) {
a = Map( x[i], count );
b = Map( y[i], count );
ST.Insert( a, b );
}
for ( int i = 0 ; i < m; ++ i ) {
scanf("%d",&ans);
printf("%d\n",ST.Query( ans ));
}
}
return 0;
}