首页 > 代码库 > AC日记——楼房 codevs 2995

AC日记——楼房 codevs 2995

2995 楼房

 

 时间限制: 1 s
 空间限制: 256000 KB
 题目等级 : 黄金 Gold
 
 
题目描述 Description

地平线(x轴)上有n个矩(lou)形(fang),用三个整数h[i],l[i],r[i]来表示第i个矩形:矩形左下角为(l[i],0),右上角为(r[i],h[i])。地平线高度为0。在轮廓线长度最小的前提下,从左到右输出轮廓线。

技术分享
输入描述 Input Description

第一行一个整数n,表示矩形个数

以下n行,每行3个整数h[i],l[i],r[i]表示第i个矩形。

输出描述 Output Description

第一行一个整数m,表示节点个数

以下m行,每行一个坐标表示轮廓线上的节点。从左到右遍历轮廓线并顺序输出节点。第一个和最后一个节点的y坐标必然为0。

样例输入 Sample Input

【样例输入】

2
3 0 2
4 1 3

【样例输入2】

5
3 -3 0
2 -1 1
4 2 4
2 3 7
3 6 8

样例输出 Sample Output

【样例输出】

6
0 0
0 3
1 3
1 4
3 4
3 0

【样例输出2】

14
-3 0
-3 3
0 3
0 2
1 2
1 0
2 0
2 4
4 4
4 2
6 2
6 3
8 3
8 0

数据范围及提示 Data Size & Hint

对于30%的数据,n<=100

对于另外30%的数据,n<=100000,1<=h[i],l[i],r[i]<=1000

对于100%的数据,1<=n<=100000,1<=h[i]<=10^9,-10^9<=l[i]<r[i]<=10^9

 

 
思路:
  离散化+线段树
  有的神犇说扫描线+堆更快,但是我不会。。
  写了一个晚上
  难在离散化和把线段放置
  线段放置要考虑蛮多的情况
  比如
  恰好公用一个端点,可是不重叠
  完全重叠
  等等等等
  离散化,用map记录下来,然后用迭代器全部存起来(stl大法好)
  然后,用离散化好的点的两点之间的间隙建立线段树
  然后把线段排序,从小到大
  然后愉快的裸flag线段树
  然后,像建树一样,一次优化<nlogn的check
  如果前面的间隙的dis不等于现在的间隙的dis就输出
  轻松ac(不知道wa了多少次re多少次)
 
 
来,上代码:
#include <map>#include <cstdio>#include <iostream>#include <algorithm>using namespace std;struct node {    long long int l,r,dis;};struct node edge[100001];inline void read_int(long long int &now_);class T_tree {    public:        int l,r,mid;        long long int dis,flag;                void mid_()        {            mid=(l+r)>>1;        }                void flag_()        {            flag=0;        }                void dis_()        {            dis=0;        }};class T_tree tree[100001*4*2];long long int n,if_Z,num=0,before=0,before_=0;long long int point[100001*2],ans=0,ans_now[100001*4],ans_dis[100001*4];char Cget;bool if_fi=true;map<long long int,long long int>if_;inline void read_int(long long int &now_){    now_=0,if_Z=1,Cget=getchar();    while(Cget<0||Cget>9)    {        if(Cget==-) if_Z=-1;        Cget=getchar();    }    while(Cget<=9&&Cget>=0)    {        now_=now_*10+Cget-0;        Cget=getchar();    }    now_*=if_Z;}inline bool cmp(struct node some1,struct node some2){    return some1.dis<some2.dis;}void tree_build(int now,int l,int r){    tree[now].l=l,tree[now].r=r;    if(l==r)    {        tree[now].dis_();        return ;    }    tree[now].mid_();    tree_build(now<<1,l,tree[now].mid);    tree_build(now<<1|1,tree[now].mid+1,r);}inline void tree_down(int now){    if(tree[now].l==tree[now].r) return ;    tree[now<<1].dis=tree[now].flag;    tree[now<<1].flag=tree[now].flag;    tree[now<<1|1].dis=tree[now].flag;    tree[now<<1|1].flag=tree[now].flag;    tree[now].flag_();}void tree_change(int now,int l,int r,long long int dis){    if(tree[now].l==l&&tree[now].r==r)    {        tree[now].dis=dis;        tree[now].flag=dis;        tree_down(now);        return ;    }    if(tree[now].flag) tree_down(now);    if(l>tree[now].mid) tree_change(now<<1|1,l,r,dis);    else if(r<=tree[now].mid) tree_change(now<<1,l,r,dis);    else    {        tree_change(now<<1,l,tree[now].mid,dis);        tree_change(now<<1|1,tree[now].mid+1,r,dis);    }}int times=0;void tree_check(int now){    if(tree[now].l==tree[now].r)    {        if(tree[now].dis!=before)        {            ans_now[++ans]=point[tree[now].l];            ans_dis[ans]=before;            ans_now[++ans]=point[tree[now].l];            ans_dis[ans]=tree[now].dis;            before=tree[now].dis;        }        return ;    }    if(tree[now].flag) tree_down(now);    tree_check(now<<1),tree_check(now<<1|1);}int main(){    read_int(n);    for(int i=1;i<=n;i++)    {        read_int(edge[i].dis),read_int(edge[i].l),read_int(edge[i].r);        if_[edge[i].l]=edge[i].l,if_[edge[i].r]=edge[i].r;    }    for(map<long long int,long long int>::iterator it=if_.begin();it!=if_.end();it++)    {        point[++num]=it->first;        it->second=num;    }    tree_build(1,1,num+1);    sort(edge+1,edge+n+1,cmp);    for(int i=1;i<=n;i++)    {        tree_change(1,if_[edge[i].l],if_[edge[i].r]-1,edge[i].dis);    }    tree_check(1);    printf("%lld\n",ans);    for(int i=1;i<=ans;i++) printf("%lld %lld\n",ans_now[i],ans_dis[i]);    return 0;}

 

附失败代码(>.<):

技术分享
#include <map>#include <cstdio>#include <iostream>#include <algorithm>using namespace std;struct node {    int l,r,dis;};struct node edge[100001];inline void read_int(int &now_);class T_tree {    public:        int l,r,mid,dis,flag;                void mid_()        {            mid=(l+r)>>1;        }                void flag_()        {            flag=0;        }                void dis_()        {            //read_int(dis);            dis=0;        }};class T_tree tree[100001*4*2];class T_tree ok[100001*4*2];int n,if_Z,num=0,before=0,before_=0;int point[100001*2],ans=0,ans_now[100001*2+1000],ans_dis[100001*2+1000];char Cget;bool if_fi=true;map<int,int>if_;inline void read_int(int &now_){    now_=0,if_Z=1,Cget=getchar();    while(Cget<0||Cget>9)    {        if(Cget==-) if_Z=-1;        Cget=getchar();    }    while(Cget<=9&&Cget>=0)    {        now_=now_*10+Cget-0;        Cget=getchar();    }    now_*=if_Z;}inline bool cmp(struct node some1,struct node some2){    return some1.dis<some2.dis;}void ok_build(int now,int l,int r){    ok[now].l=l,ok[now].r=r;    if(l==r) return ;    ok[now].mid_();    ok_build(now<<1,l,ok[now].mid);    ok_build(now<<1|1,ok[now].mid+1,r);}void ok_down(int now){    if(ok[now].l==ok[now].r) return ;    ok[now<<1].dis=ok[now].flag;    ok[now<<1].flag=ok[now].flag;    ok[now<<1|1].dis=ok[now].flag;    ok[now<<1|1].flag=ok[now].flag;    ok[now].flag=0;}void ok_change(int now,int l,int r){    if(ok[now].dis) return ;    if(ok[now].l==ok[now].r)    {        ok[now].dis=1;        ok[now].flag=1;        ok_down(now);        return ;    }    if(ok[now].flag) ok_down(now);    if(l>ok[now].mid) ok_change(now<<1|1,l,r);    else if(r<=ok[now].mid) ok_change(now<<1,l,r);    else    {        ok_change(now<<1,l,ok[now].mid);        ok_change(now<<1|1,ok[now].mid+1,r);    }}bool ok_ko(int now,int to){    if(ok[now].dis) return true;    if(ok[now].l==ok[now].r&&ok[now].l==to)    {        return false;    }    if(ok[now].flag) ok_down(now);    if(ok[now].l>to) return ok_ko(now<<1|1,to);    else return ok_ko(now<<1,to);}void tree_build(int now,int l,int r){    tree[now].l=l,tree[now].r=r;    if(l==r)    {        tree[now].dis_();        return ;    }    tree[now].mid_();    tree_build(now<<1,l,tree[now].mid);    tree_build(now<<1|1,tree[now].mid+1,r);}inline void tree_down(int now){    if(tree[now].l==tree[now].r) return ;    tree[now<<1].dis=tree[now].flag;    tree[now<<1].flag=tree[now].flag;    tree[now<<1|1].dis=tree[now].flag;    tree[now<<1|1].flag=tree[now].flag;    tree[now].flag_();}void tree_change(int now,int l,int r,int dis){    if(tree[now].l==l&&tree[now].r==r)    {        tree[now].dis=dis;        tree[now].flag=dis;        tree_down(now);        return ;    }    if(tree[now].flag) tree_down(now);    if(l>tree[now].mid) tree_change(now<<1|1,l,r,dis);    else if(r<=tree[now].mid) tree_change(now<<1,l,r,dis);    else    {        tree_change(now<<1,l,tree[now].mid,dis);        tree_change(now<<1|1,tree[now].mid+1,r,dis);    }}int times=0;void tree_check(int now){    if(tree[now].l==tree[now].r)    {        /*if(tree[now].dis!=before_)        {            times++;            if(times==1)            {                printf("%d %d\n",point[tree[now].l],before);                printf("%d %d\n",point[tree[now].l],tree[now].dis);            }            else            {                printf("%d %d\n",point[tree[now].l],tree[now].dis);            }            before_=tree[now].dis;        }*/        //printf("(%d,%d)",point[tree[now].l],tree[now].dis);        if(tree[now].l==num+1)        {            if(before!=0)            {                //printf("%d %d\n",point[num],before);                //printf("%d %d\n",point[num],0);                ans_now[++ans]=point[num];                ans_dis[ans]=before;                ans_now[++ans]=point[num];                ans_dis[ans]=0;            }        }        else        {            if(ok_ko(1,tree[now].l-1))            {                if(tree[now].dis!=before)                {                    //printf("%d %d\n%d %d\n",point[tree[now].l],before,point[tree[now].l],tree[now].dis);                        ans_now[++ans]=point[tree[now].l];                    ans_dis[ans]=before;                    ans_now[++ans]=point[tree[now].l];                    ans_dis[ans]=tree[now].dis;                    before=tree[now].dis;                }            }            else            {                if(before!=0)                {                    //printf("%d %d\n",point[tree[now].l-1],point[tree[now].l]);                    ans_now[++ans]=point[tree[now].l-1];                    ans_dis[ans]=before;                    ans_now[++ans]=point[tree[now].l-1];                    ans_dis[ans]=0;                    ans_now[++ans]=point[tree[now].l];                    ans_dis[ans]=0;                    ans_now[++ans]=point[tree[now].l];                    ans_dis[ans]=tree[now].dis;                    before=tree[now].dis;                }            }        }        //printf("(%d %d)\n",point[tree[now].l],tree[now].dis);        return ;    }    if(tree[now].flag) tree_down(now);    tree_check(now<<1),tree_check(now<<1|1);}int main(){    read_int(n);    for(int i=1;i<=n;i++)    {        read_int(edge[i].dis),read_int(edge[i].l),read_int(edge[i].r);        if_[edge[i].l]=edge[i].l,if_[edge[i].r]=edge[i].r;    }  //  printf("\n\n");    for(map<int,int>::iterator it=if_.begin();it!=if_.end();it++)    {        point[++num]=it->first;        it->second=num;    //    printf("%d %d\n",num,point[num]);    }    tree_build(1,1,num+1);    ok_build(1,0,num-1);    ok_change(1,0,0);    sort(edge+1,edge+n+1,cmp);    for(int i=1;i<=n;i++)    {        printf("%d %d\n",if_[edge[i].l],if_[edge[i].r]);    }    printf("\n\n");    for(int i=1;i<=n;i++)    {        //printf("%d %d %d\n\n",if_[edge[i].l],if_[edge[i].r],edge[i].dis);        tree_change(1,if_[edge[i].l],if_[edge[i].r],edge[i].dis);           ok_change(1,if_[edge[i].l],if_[edge[i].r]-1);           printf("%d %d\n",if_[edge[i].l],if_[edge[i].r]-1);        //ans=0;        //before=0;        //tree_check(1);        //printf("\n");        //printf("%d %d %d\n",if_[edge[i].l],if_[edge[i].r],edge[i].dis);    }    printf("\n\n");    //ans=0;    //before=0;    tree_check(1);    //printf("\n\n");    printf("%d\n",ans);    for(int i=1;i<=ans;i++) printf("%d %d\n",ans_now[i],ans_dis[i]);    return 0;}
View Code

 

AC日记——楼房 codevs 2995