zoukankan      html  css  js  c++  java
  • 0SGU 128 snake (&& ZOJ 3521) 尺取,排序二叉树,线段树 难度:2

    128. Snake

    time limit per test: 0.25 sec. 
    memory limit per test: 4096 KB

     

    There are N points given by their coordinates on a plane. All coordinates (xi,yi) are integers in a range from -10000 up to 10000 inclusive . It is necessary to construct a broken line satisfying the following conditions:
    1. The broken line should be closed.
    2. End points of each segment (verteces) of the broken line can only be the given points, and all given points should be used.
    3. Each two consecutive segments of the broken line should form a corner of 90 degrees in each vertex point.
    4. The sides of the broken line should be parallel to coordinate axes.
    5. The broken line should have no self-crossing and self-contact.
    6. The broken line should have the minimal length.
    You have to either find the length L of the constructed broken line, or determine that it is impossible to construct such a broken line.

     

    Input

    First line contains the number N (4 <= N <= 10000) - amount of points. Each of the following N lines contains coordinates of points separated by space xi and yi (1 <= i <= N). Points are given in random order.

     

    Output

    First line should contain the length of the broken line L or 0 if there is no solution.

     

    Sample Input

    Sample Output

    4
    0 0
    0 3
    3 3
    3 0
    

    Sample Output

    12
    看了题解,发现这个不自交是每个点只有两条边的意思,所以必然从左下角出发只有一个解,注意到这一点之后胡乱搞搞就过了,,,,
    大概就是,首先确定整个图是由平行于x,y轴线段组成的,每个点的度都是2的图
    然后,对每个x段,在起点取y值,在终点去掉y值,对应在线段树上就是起点时+1,终点时-1,x段互相之间必然不相交
    所以统计是否相交只需要看y段和x段是否交,对所有的y段看是否有(y1,y2)的开区间内的点y0已经存在线段树上了(也就是有一条高度为y1<y0<y2的线段,这个时候线段还在树上所以x1<=x
    <=x2)
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define lx (x<<1)
    #define rx ((x<<1)|1)
    #define MID ((l+r)>>1)
    const int  maxn=10001;
    int n;
    int dat[maxn<<4];
    struct pnt{
        int x,y,ind;
    }p[maxn];
    int e[maxn][3],len[maxn];
    bool vis[maxn*2];
    void dfs(int s){
        vis[s]=true;
        for(int i=0;i<2;i++){
            int to=e[s][i];
            if(!vis[to])dfs(to);
        }
    }
    bool cmpx(pnt p1,pnt p2){
        if(p1.x!=p2.x)return p1.x<p2.x;
        return p1.y<p2.y;
    }
    bool cmpy(pnt p1,pnt p2){
        if(p1.y!=p2.y)return p1.y<p2.y;
         return p1.x<p2.x;
    }
    void update(int pos,int del ,int l,int r,int x){
        if(l==r){dat[x]+=del;return ;}
        if(pos<=MID)update(pos,del,l,MID,lx);
        else update(pos,del,MID+1,r,rx);
        dat[x]=dat[lx]+dat[rx];
    }
    int query(int L,int R,int l,int r,int x){
        if(L<=l&&r<=R)return dat[x];
        int ans=0;
        if(L<=MID)ans+=query(L,R,l,MID,lx);
        if(MID<R)ans+=query(L,R,MID+1,r,rx);
        return ans;
    }
    void addedge(int f,int t){
        if(len[f]<3)e[f][len[f]++]=t;
        if(len[t]<3)e[t][len[t]++]=f;
    }
    int main(){
       scanf("%d",&n);
       int maxy=0;
       for(int i=0;i<n;i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].x+=maxn;
            p[i].y+=maxn;
            maxy=max(maxy,p[i].y);
       }
       sort(p,p+n,cmpx);
       for(int i=0;i<n;i++){
            p[i].ind=i;
       }
       int ans=0;
       sort(p,p+n,cmpy);
       for(int i=1;i<n;i+=2){
            if(p[i].y==p[i-1].y){addedge(p[i-1].ind,p[i].ind);ans+=p[i].x-p[i-1].x;}
       }
       sort(p,p+n,cmpx);
       for(int i=1;i<n;i+=2){
            if(p[i].x==p[i-1].x){addedge(p[i-1].ind,p[i].ind);ans+=p[i].y-p[i-1].y;}
       }
       for(int i=0;i<n;i++){
            if(len[i]!=2){puts("0");return 0;}
       }
       dfs(0);
       for(int i=0;i<n;i++){
            if(!vis[i]){puts("0");return 0;}
       }
       memset(vis,0,sizeof(vis));
       for(int i=0;i<n;i++){
            int x1=p[i].x,x2=p[e[i][0]].x;
            int y1=p[i].y,y2=p[e[i][1]].y;
            if(vis[i])update(y1,-1,1,maxy,1);
            int k1=y2>2?query(1,y2-1,1,maxy,1):0;//因为是重叠着做的而不是分开来更新所有x再检验的,也就是说这个x对应的y需要被取下但是还没取,所以通过事件顺序没法规范发生,需要注意去掉端点问题
            int k2= query(1,y1,1,maxy,1);
            if(y2-y1>1 && (k1-k2)>0){puts("0");return 0;}
            if(!vis[i])update(y1,1,1,maxy,1);
            vis[i] = !vis[i];
            vis[e[i][0]] = !vis[e[i][0]];
       }
       printf("%d\n",ans);
        return 0;
    }
    

      

  • 相关阅读:
    The Brain vs Deep Learning Part I: Computational Complexity — Or Why the Singularity Is Nowhere Near
    unity3d NGUI多场景共用界面制作
    python第三方库系列之十九--python測试使用的mock库
    oracle之单行函数
    Andropid自己定义组件-坐标具体解释
    [WebGL入门]二,開始WebGL之前,先了解一下canvas
    【BZOJ2318】【spoj4060】game with probability Problem 概率DP
    苹果改版之后,关于隐私协议加入的问题解决方式
    Binary Tree Level Order Traversal II
    首届中国智慧城市协同创新峰会将于6月20日在大连隆重举行
  • 原文地址:https://www.cnblogs.com/xuesu/p/4014989.html
Copyright © 2011-2022 走看看