您的位置:首页 > 其它

【ZOJ】3299 Fall the Brick 线段树

2014-06-25 14:02 232 查看
Fall the Brick

Time Limit: 3 Seconds
Memory Limit: 32768 KB

Now the God is very angry, so he wants to punish the lazy, greedy humans.He chooses to throw some lines of bricks (just down from the very high Heaven).These days the God lives in a 2D world, so he just throw the bricks in a
vertical plane.Each time, the God throws a line of bricks. The width of each brick is 1, and the length will be given.

t__nt is a hero in the world and he is trying his best to save the world.Now he has made
m horizontal boards in the air with his magic power to stop the bricks.If one brick falls onto a board, it can not fall down any more.Notice that, for a line of bricks, consecutive bricks are not connected. So when some bricks
touch a board, the others will continues to fall down.
Now, t__nt wants to know how many bricks each board holds after the God's crazy action.He asks you, an ACMer, to help him.



Input

There are no more then 10 cases. There is a blank line between consecutive cases.The first line of each case contains two integers
n, m (0 < n, m <= 100000), indicating the number of lines of bricks and number of horizontal boards made by t__nt.n lines follow, each contains two integers
li, ri (0 <= li <
ri <= 30000000). li and ri is the x-coordinates for the left side and the right side of the line of bricks.m lines follow, each contains three integers
ai, bi, and hi(0 <=
ai < bi <= 30000000; 0 < hi < 1000000000), which means that board i is at height
hi and the extreme points are ai and
bi.You may assume no two boards with same height will overlap with each other.

Output

For each case, print m lines. The ith line means the number of bricks on board i at last.Print a blank line after each case.

Sample Input

1 2
1 8
1 5 8
3 7 6

Sample Output

4
2


Author: CHEN, Zhangyi

Source: ZOJ Monthly, February 2010

传送门:【ZOJ】3299 Fall
the Brick

题目大意:

n排板砖从天上掉落,用m块板去接板砖(n , m <= 100000)。其中每排板砖覆盖范围为[L,R],每块板高度为H,覆盖范围为[L,R],一排板砖的一部分掉落到某块板上后便停止掉落,然后其余板砖的继续下落,问最后每块板上有多少板砖。(0 <= L,R <= 30000000,0<H<1000000000)

题目分析:

将板砖覆盖的区间和板覆盖的区间离散化成互不相交的区间。然后先将板插入区间中,得到属于每个板的区间,然后插入板砖,为每个区间累加覆盖次数。最后每个区间覆盖次数*覆盖区间原长便加到它属于的板的计数器中。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

typedef long long Int ;

#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define rt o , l , r
#define root 1 , 1 , n
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define clear( A , X ) memset ( A , X , sizeof A )

const int maxN = 100005 ;

struct Line {
	int l , r , h , idx ;
	Line () {}
	void input ( int __idx ) {
		scanf ( "%d%d%d" , &l , &r , &h ) ;
		idx = __idx ;
	}
} ;

Line line[maxN] ;
Line brick[maxN] ;
Int ans[maxN << 4] ;
int add[maxN << 4] ;
int set[maxN << 4] ;
int a[maxN << 2] ;

int cmp ( const Line &a , const Line &b ) {
	return a.h < b.h ;
}

int Unique ( int a[] , int n ) {
	int cnt = 1 ;
	sort ( a + 1 , a + n + 1 ) ;
	for ( int i = 2 ; i <= n ; ++ i ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ;
	return cnt ;
}

int Search ( int x ,  int l , int r ) {
	while ( l < r ) {
		int m = mid ;
		if ( a[m] >= x ) r = m ;
		else l = m + 1 ;
	}
	return l ;
}

void PushDown ( int o ) {
	if ( set[o] ) {
		set[ls] = set[rs] = set[o] ;
		set[o] = 0 ;
	}
	if ( add[o] ) {
		add[ls] += add[o] ;
		add[rs] += add[o] ;
		add[o] = 0 ;
	}
}

void Update ( int L , int R , int v , int o , int l , int r ) {
	if ( L <= l && r <= R ) {
		if ( v ) set[o] = v ;
		else ++ add[o] ;
		return ;
	}
	PushDown ( o ) ;
	int m = mid ;
	if ( L <= m ) Update ( L , R , v , lson ) ;
	if ( m <  R ) Update ( L , R , v , rson ) ;
}

void Query ( int o , int l , int r ) {
	if ( l == r ) {
		ans[set[o]] += add[o] * ( a[r + 1] - a[l] ) ;
		return ;
	}
	PushDown ( o ) ;
	int m = mid ;
	Query ( lson ) ;
	Query ( rson ) ;
}

void work () {
	int n , m , cnt ;
	while ( ~scanf ( "%d%d" , &n , &m ) ) {
		clear ( add , 0 ) ;
		clear ( set , 0 ) ;
		clear ( ans , 0 ) ;
		cnt = 0 ;
		for ( int i = 1 ; i <= n ; ++ i ) {
			scanf  ( "%d%d" , &brick[i].l , &brick[i].r ) ;
			a[++ cnt] = brick[i].l ;
			a[++ cnt] = brick[i].r ;
		}
		for ( int i = 1 ; i <= m ; ++ i ) {
			line[i].input ( i ) ;
			a[++ cnt] = line[i].l ;
			a[++ cnt] = line[i].r ;
		}
		cnt = Unique ( a , cnt ) ;
		//for ( int i = 1 ; i <= cnt ; ++ i ) printf ( "%d " , a[i] ) ;
		sort ( line + 1 , line + m + 1 , cmp ) ;
		for ( int i = 1 ; i <= m ; ++ i ) {
			int L = Search ( line[i].l , 1 , cnt + 1 ) ;
			int R = Search ( line[i].r , 1 , cnt + 1 ) ;
			Update ( L , R - 1 , line[i].idx , 1 , 1 , cnt - 1 ) ;
		}
		for ( int i = 1 ; i <= n ; ++ i ) {
			int L = Search ( brick[i].l , 1 , cnt + 1 ) ;
			int R = Search ( brick[i].r , 1 , cnt + 1 ) ;
			Update ( L , R - 1 , 0 , 1 , 1 , cnt - 1 ) ;
		}
		Query ( 1 , 1 , cnt - 1 ) ;
		for ( int i = 1 ; i <= m ; ++ i ) printf ( "%lld\n" , ans[i] ) ;
		printf ( "\n" ) ;
	}
}

int main () {
	work () ;
	return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: