您的位置:首页 > 其它

zoj3299 Fall the Brick map 离散化

2013-05-16 23:52 330 查看
正在缓慢地学习交大的《题目与解读》这本书,里面很多题目都是很有意思的。

zoj3299 Fall the Brick。

给一些条状的方块,和一些水平的board,求每个board上有多少个单位方块。单位方块长度为1,会落在该位置最高的一个board上。

比较直观的是线段树的解法吧。

书里写到了用map的做法。

其实这种离散化后用(l,1),(r,-1)的事件来处理大范围坐标的题目也见过很多次了。不过还是不够熟练,思考、调试了半天。。。

具体的处理方法:

1.将每个条块的变为两个事件(l,0,1)表示加入一个条块,(r,0,-1)表示减去一个条块。将第i个board也变为两个事件(l,i,1)(r,i,-1)。

2.离散化。这里我没有离散化,因为只要从左到右扫一遍,我就直接排序扫过去了。如果两个点的x坐标相同,相减为0,不会造成错误。

3.排序这些事件,从左到右处理:

用tcnt计数,记录前一个区段有几个条块。用pre保存这个区段的起点。

对于每个事件,先处理这个事件之前的区间,总单位方块数量就是条块的数量乘以区间长度,用map找到之前区间中最高的一个board,将这些方块加入该board中。

然后处理这个事件。条块是1就将tcnt++,-1就tcnt--。如果是board,就在map中加入或删除该board。

4.然后输出答案啦。

这种离散化的问题和这种处理方法还需要多加练习,否则碰到陌生的问题很难想清楚,还有速度,速度。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define NN 401000

int n,m;

struct bar{
    int h,l,r;
    long long c;
}c[NN];

struct node{
    int l,v,c;
    void init(int a,int b,int cc){l=a;v=b;c=cc;}
}sx[NN],tn;

bool cmp(node a,node b){
    if (a.l==b.l) return a.c<b.c;
    return a.l<b.l;
}

map<int,int> mp;

void work(int tx){
    mp.clear();
    int i,j,tcnt=0,pre=sx[1].l;
    int tmp;
    for(i=1;i<=tx;++i){
        if (mp.rbegin()!=mp.rend()){
            tmp=mp.rbegin()->second;
            c[tmp].c+=((long long)sx[i].l-pre)*tcnt;
        }
        if (sx[i].v>0){
            if (sx[i].c==1) mp[c[sx[i].v].h]=sx[i].v;
            else mp.erase(c[sx[i].v].h);
        }
        else{
            if (sx[i].c==1) tcnt+=1;
            else tcnt-=1;
        }
        pre=sx[i].l;
    }
}

int main(){
    int tx,i,lb,rb;
    while(scanf("%d%d",&n,&m)!=EOF){
        tx=0;
        for(i=1;i<=n;++i){
            scanf("%d%d",&lb,&rb);
            tn.init(lb,0,1);
            sx[++tx]=tn;
            tn.init(rb,0,-1);
            sx[++tx]=tn;
        }
        for(i=1;i<=m;++i){
            scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].h);
            c[i].c=0;
            tn.init(c[i].l,i,1);
            sx[++tx]=tn;
            tn.init(c[i].r,i,-1);
            sx[++tx]=tn;

        }
        sort(sx+1,sx+tx+1,cmp);

        work(tx);
        for(i=1;i<=m;++i){
            printf("%lld\n",c[i].c);
        }
        printf("\n");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: