【洛谷P1382】楼房

这个题先离散化,然后强行用线段树统计每个点的高度,就可以了,只需要区间修改和单点查询就好,不过数据范围可能是假的……因为题目100000,然后我按照线段树开了4倍空间,然后re了,直到开了8倍……

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int m;
struct es
{
    int h,x,y;
}ing[200010];
struct in
{
    int l,r,mx,add;
}ter[800040];
int a[800020],len,tot,a1[1000020],a2[1000020];
inline void build(int l,int r,int w)
{
    ter[w].mx=0,ter[w].l=l,ter[w].r=r,ter[w].add=0;
    if(l==r)
        return;
    int mid=l+r>>1;
    build(l,mid,w<<1),build(mid+1,r,w<<1|1); 
}
inline void d(int w)
{
    if(!ter[w].add)
        return;
    ter[w<<1].mx=max(ter[w<<1].mx,ter[w].add);
    ter[w<<1|1].mx=max(ter[w<<1|1].mx,ter[w].add);
    ter[w<<1].add=max(ter[w].add,ter[w<<1].add);
    ter[w<<1|1].add=max(ter[w].add,ter[w<<1|1].add);
    ter[w].add=0;
}
inline void u(int w)
{ 
    ter[w].mx=max(ter[w<<1].mx,ter[w<<1|1].mx);
}
void cha(int l,int r,int x,int w)//区间修改赋值 
{
    if(ter[w].l==l&&ter[w].r==r)
    {
        ter[w].mx=max(ter[w].mx,x),ter[w].add=max(ter[w].add,x);return;
    }
    d(w);
    int mid=ter[w].l+ter[w].r>>1;
    if(r<=mid)
        cha(l,r,x,w<<1);
    else if(l>mid)
        cha(l,r,x,w<<1|1);
    else
        cha(l,mid,x,w<<1),cha(mid+1,r,x,w<<1|1);
    u(w);
}
inline int ask(int l,int w)//单点查询 
{
    if(l==ter[w].l&&l==ter[w].r)
        return ter[w].mx;
    d(w);
    int re=0,mid=ter[w].l+ter[w].r>>1;
    if(l<=mid)
        re=ask(l,w<<1);
    else
        re=ask(l,w<<1|1);
    u(w);
    return re;
}
int main()
{
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&ing[i].h,&ing[i].x,&ing[i].y),a[i*2-1]=ing[i].x,a[i*2]=ing[i].y;
    sort(a+1,a+1+m*2);//排序,之后离散化 
    int len=unique(a+1,a+1+m*2)-a-1;
    build(1,len,1);
    for(int i=1;i<=m;i++)
    {
        int x=lower_bound(a+1,a+1+len,ing[i].x)-a;
        int y=lower_bound(a+1,a+1+len,ing[i].y)-a;
        cha(x,y-1,ing[i].h,1);//因为处理的是区间,有i个点就有i-1个区间 
    }//因为对答案有影响的只有矩形的两端,所以统计答案的时候只关心她们就好 
    for(int i=1;i<=len;i++)
    {
        a1[i]=a[i],a2[i]=ask(i,1);//询问高度 
        if(a2[i]!=a2[i-1])
            tot++;
    }
    printf("%d\n",tot*2);
    for(int i=1;i<=len;i++)
        if(a2[i]!=a2[i-1])//如果高度产生落差,说明这是答案的之一 
        {
            printf("%d %d\n",a1[i],a2[i-1]);
            printf("%d %d\n",a1[i],a2[i]); 
        }
} 

 

posted @ 2017-10-28 22:24  那一抹落日的橙  阅读(194)  评论(0编辑  收藏  举报