zoj 3299 Fall the Brick

本文介绍了一个砖块掉落模拟问题,通过使用线段树等数据结构来解决如何计算多个水平板接住从天而降的不连续砖块的数量。文章详细阐述了算法实现步骤,包括坐标离散化、线段树构建及查询过程。
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 nm (0 < nm <= 100000), indicating the number of lines of bricks and number of horizontal boards made by t__nt. n lines follow, each contains two integers liri (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 aibi, 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

题意:天空中掉下来n个bricks,你用m个boards去接,已知brick的左右端点,board的左右端点以及高度,并且一块brick不是连续的,求每块board接到的brick数量。

首先离散化坐标,然后根据离散化的坐标,把整个座标轴分成了一段一段的,以这些段为线段树的叶子节点,建树,每个brick就是对应区间+1,查询的时候,需要在查的同时把合适的区间置0。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

typedef long long ll;
#define rep(i,s,t) for(int i=s;i<t;i++)
#define red(i,s,t) for(int i=s-1;i>=t;i--)
#define ree(i,now) for(int i=head[now];i!=-1;i=edge[i].next)
#define clr(a,v) memset(a,v,sizeof a)
#define L t<<1
#define R t<<1|1
#define MID int mid=(l+r)>>1
#define max(a,b) (a<b?b:a)
#define min(a,b) (a<b?a:b)
#define SQR(a) ((a)*(a))

inline int input(){
	int ret=0;bool isN=0;char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') isN=1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		ret=ret*10+c-'0';
		c=getchar();
	}
	return isN?-ret:ret;
}

inline void output(ll x){    
    if(x<0){    
        putchar('-');x=-x;    
    }    
    int len=0,data[20];    
    while(x){    
        data[len++]=x%10;x/=10;    
    }    
    if(!len)    data[len++]=0;    
    while(len--)   
        putchar(data[len]+48);    
    putchar('\n');  
}  

const int MAXN=100001;
int to[MAXN<<2],cnt,a[MAXN<<2];
ll sum[MAXN<<4];
int lazy[MAXN<<4];
int len[MAXN<<4];
ll ans[MAXN],A;
int n,m;

struct BRICKS{
	int x,y;
	void read(){
		x=input(),y=input();//y--;
		to[++cnt]=x,to[++cnt]=y;
	}
}b[MAXN];
struct BOARDS{
	int x,y,h,id;
	void read(int _i){
		x=input(),y=input(),h=input();//y--;
		to[++cnt]=x,to[++cnt]=y;
	}
}bo[MAXN];
bool cmp(BOARDS i,BOARDS j){
	return i.h>j.h;
}

inline void push_up(int t){
	sum[t]=sum[L]+sum[R];
}

inline void push_down(int t){
	if(lazy[t]){
		lazy[L]+=lazy[t];
		lazy[R]+=lazy[t];
		sum[L]+=(ll)lazy[t]*(ll)len[L];
		sum[R]+=(ll)lazy[t]*(ll)len[R];
		lazy[t]=0;
	}
}

inline void build(int t,int l,int r){
	lazy[t]=0;
	sum[t]=0;
	if(l==r){
		len[t]=a[l];
	}
	else{
		MID;
		build(L,l,mid);
		build(R,mid+1,r);
		len[t]=len[L]+len[R];
	}
}

inline void add(int t,int l,int r,int x,int y,int v){
	if(l>=x && r<=y){
		lazy[t]+=v;
		sum[t]+=v*len[t];
	}
	else{
		push_down(t);
		MID;
		if(y<=mid) add(L,l,mid,x,y,v);
		else if(x>mid) add(R,mid+1,r,x,y,v);
		else{
			add(L,l,mid,x,mid,v);
			add(R,mid+1,r,mid+1,y,v);
		}
		push_up(t);
	}
}

inline void query(int t,int l,int r,int x,int y){
	if(sum[t]<=0) return;
	if(l>=x && r<=y){
		A+=sum[t];
		lazy[t]=0;
		sum[t]=0;
		return;
	}
	push_down(t);
	MID;
	if(y<=mid) query(L,l,mid,x,y);
	else if(x>mid)  query(R,mid+1,r,x,y);
	else{
		query(L,l,mid,x,mid),query(R,mid+1,r,mid+1,y);
	}
	push_up(t);
}

int main(){
	//freopen("1","r",stdin);
	while(~scanf("%d%d",&n,&m)){
		cnt=0;
		rep(i,0,n){
			b[i].read();
		}
		rep(i,0,m){
			bo[i].read(i);
		}
		sort(to+1,to+cnt+1);
		cnt=unique(to+1,to+cnt+1)-(to+1);
		rep(i,0,n){
			b[i].x=lower_bound(to+1,to+cnt+1,b[i].x)-(to+1)+1;
			b[i].y=lower_bound(to+1,to+cnt+1,b[i].y)-(to+1)+1;
		}
		rep(i,0,m){
			bo[i].id=i;
			bo[i].x=lower_bound(to+1,to+cnt+1,bo[i].x)-(to+1)+1;
			bo[i].y=lower_bound(to+1,to+cnt+1,bo[i].y)-(to+1)+1;
		}
		rep(i,1,cnt){
			a[i]=to[i+1]-to[i];
		}
		a[cnt]=0;	
		build(1,1,cnt);
		sort(bo,bo+m,cmp);
		rep(i,0,n){
			add(1,1,cnt,b[i].x,b[i].y-1,1);
		}
	
		rep(i,0,m){
			A=0;query(1,1,cnt,bo[i].x,bo[i].y-1);
			ans[bo[i].id]=A;
		}
		rep(i,0,m){
			output(ans[i]);
		}
                puts("");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值