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.

ZOJ3299:Fall the Brick(区间更新)_第1张图片

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;
}


你可能感兴趣的:(ZOJ)