ZOJ3299:Fall the Brick(区间更新)

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块板砖从天而降,为了不被砸死,弄了m块木板来挡,每块板砖长度为1单位,给出连续板砖的范围还有木板的范围与高度,问最后每块木板上有几块板砖
 
思路:由于数字大,首先要离散化,然后位于高处的木板与低处的木板有重合的话,高处先挡下,然后再去计算
 
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
#define ls 2*i
#define rs 2*i+1
#define up(i,x,y) for(i=x;i<=y;i++)
#define down(i,x,y) for(i=x;i>=y;i--)
#define mem(a,x) memset(a,x,sizeof(a))
#define w(a) while(a)
#define LL long long
const double pi = acos(-1.0);
#define N 100005
#define mod 19999997
const int INF = 0x3f3f3f3f;
#define exp 1e-8

LL sum[1<<20],col[1<<20],ans[N];
int seg[N*4],len;
bool flag[1<<20];
int n,m;
struct brick
{
    int l,r,lid,rid;
}a[N];
struct board
{
    int l,r,h,lid,rid,id;
}b[N];

int cmp(board a,board b)//高的木板在前
{
    return a.h>b.h;
}

void push_down(int i,int l,int r)
{
    int mid = (l+r)/2;
    if(col[i])
    {
        col[ls] += col[i];
        col[rs] += col[i];
        sum[ls] += (LL)col[i]*(seg[mid+1]-seg[l]);
        sum[rs] += (LL)col[i]*(seg[r+1]-seg[mid+1]);
        col[i] = 0;
    }
}

void build(int i,int l,int r)
{
    sum[i] = col[i] = 0;
    flag[i] = false;
    if(l==r) return;
    int mid = (l+r)/2;
    build(ls,l,mid);
    build(rs,mid+1,r);
}

void updata1(int L,int R,int val,int l,int r,int i)
{
    if(L<=l && r<=R)
    {
        col[i]+=val;
        sum[i]+=val*(seg[r+1]-seg[l]);
        return;
    }
    push_down(i,l,r);
    int mid = (l+r)/2;
    if(L<=mid)
    updata1(L,R,val,l,mid,ls);
    if(R>mid)
    updata1(L,R,val,mid+1,r,rs);
    sum[i] = sum[ls]+sum[rs];
}

void updata2(int L,int R,int l,int r,int i)
{
    if(flag[i]) return;
    if(L<=l && r<=R)
    {
        flag[i] = true;
        sum[i]=0;
        return;
    }
    push_down(i,l,r);
    int mid = (l+r)/2;
    if(L<=mid)
    updata2(L,R,l,mid,ls);
    if(R>mid)
    updata2(L,R,mid+1,r,rs);
    sum[i] = sum[ls]+sum[rs];
}

LL query(int L,int R,int l,int r,int i)
{
    if(flag[i]) return 0;
    if(L<=l && r<=R)
    {
        return sum[i];
    }
    push_down(i,l,r);
    int mid = (l+r)/2;
    LL ret = 0;
    if(L<=mid)
    ret+=query(L,R,l,mid,ls);
    if(R>mid)
    ret+=query(L,R,mid+1,r,rs);
    return ret;
}

int main()
{
    int i,j,k;
    w(~scanf("%d%d",&n,&m))
    {
        len = 0;
        up(i,0,n-1)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
            seg[len++] = a[i].l;
            seg[len++] = a[i].r;
        }
        up(i,0,m-1)
        {
            scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].h);
            b[i].id = i;
            seg[len++] = b[i].l;
            seg[len++] = b[i].r;
        }
        //排序,去重,然后离散化
        sort(seg,seg+len);
        len = unique(seg,seg+len)-seg;
        up(i,0,n-1)
        {
            a[i].lid = lower_bound(seg,seg+len,a[i].l)-seg;
            a[i].rid = lower_bound(seg,seg+len,a[i].r)-seg;
        }
        up(i,0,m-1)
        {
            b[i].lid = lower_bound(seg,seg+len,b[i].l)-seg;
            b[i].rid = lower_bound(seg,seg+len,b[i].r)-seg;
        }
        build(1,0,len-1);//建树
        up(i,0,n-1)//对每个区间有几块板砖进行更新
        {
            updata1(a[i].lid,a[i].rid-1,1,0,len-1,1);
        }
        sort(b,b+m,cmp);
        up(i,0,m-1)//查询每块木板上有几块板砖,然后对于已挡住的部分进行清零处理
        {
            ans[b[i].id] = query(b[i].lid,b[i].rid-1,0,len-1,1);
            updata2(b[i].lid,b[i].rid-1,0,len-1,1);
        }
        up(i,0,m-1)
        printf("%lld\n",ans[i]);
        printf("\n");
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值