码迷,mamicode.com
首页 > 其他好文 > 详细

AC日记——楼房 codevs 2995

时间:2017-01-05 22:51:51      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:display   closed   printf   input   long   als   alt   success   扫描线   

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

标签:display   closed   printf   input   long   als   alt   success   扫描线   

原文地址:http://www.cnblogs.com/IUUUUUUUskyyy/p/6254196.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!