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;
}

  

0SGU 128 snake (&& ZOJ 3521) 尺取,排序二叉树,线段树 难度:2的更多相关文章

  1. 【BZOJ4552】排序(线段树,二分答案)

    [BZOJ4552]排序(线段树,二分答案) 题面 BZOJ 题解 好神的题啊 直接排序我们做不到 怎么维护? 考虑一下,如果我们随便假设一个答案 怎么检验它是否成立? 把这个数设成\(1\),其他的 ...

  2. 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)

    2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...

  3. ZOJ 3521 Fairy Wars oj错误题目,计算几何,尺取法,排序二叉树,并查集 难度:2

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3521 ATTENTION:如果用long long 减小误差,这道题只能用 ...

  4. ZOJ 1610 Count the Colors (线段树区间更新)

    题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...

  5. ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)

    ZOJ 3597 题意是说有n把枪,有m个靶子,每把枪只有一发子弹(也就是说一把枪最多只能打一个靶子), 告诉你第 i 把枪可以打到第j个靶, 现在等概率的出现一个连续的P把枪,在知道这P把枪之后,你 ...

  6. ZOJ 1859 Matrix Searching(二维线段树)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1859 Matrix Searching Time Limit: 10 Seco ...

  7. zoj 1610 Count the Colors(线段树延迟更新)

    所谓的懒操作模板题. 学好acm,英语很重要.做题的时候看不明白题目的意思,我还拉着队友一块儿帮忙分析题意.最后确定了是线段树延迟更新果题.我就欣欣然上手敲了出来. 然后是漫长的段错误.... 第一次 ...

  8. [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树

    Brief Description DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列. 现在他想支持两种操作: 0, l, r: 将a[l..r]原地升序排序. 1, l, r: 将a ...

  9. bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

随机推荐

  1. 【前端】Vue.js实现实例搜索应用

    实例搜索应用 实现效果: 实现代码与注释: <!DOCTYPE html> <html> <head> <title>实例搜索</title> ...

  2. Python3基础 函数 递归 阶乘与斐波那契数列

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  3. Eclipse中离线安装ADT插件详细教程

    在搭建Android开发环境的时候,我们需要为Eclipse安装ADT(Android Development Tools)插件,这个插件可以为用户提供一个强大的Android集成开发环境.通过给Ec ...

  4. redis安装使用配置

    一.安装前的准备 下载redis http://redis.io/download https://github.com/mythz/redis-windows 下载Windows版客户端net版sd ...

  5. 移动端Css初始化

    @charset "utf-8"; /* 禁用iPhone中Safari的字号自动调整 */ html { -webkit-text-size-adjust: %; -ms-tex ...

  6. 2、Python快速入门(0529)

    要素7:输入/输出 1.python解释器提供了3种标准文件对象,分别为标准输入.标准输出和标准错误,它们在sys模块中分别以sys.stdin.sys.stdout和sys.stderr形式提供: ...

  7. HDU 6060 RXD and dividing(思维+计算贡献值)

    http://acm.hdu.edu.cn/showproblem.php?pid=6060 题意: 给定一棵 n 个节点的树,1 为根.现要将节点 2 ~ n 划分为 k 块,使得每一块与根节点形成 ...

  8. POJ 1753 Flip Game(bfs+位压缩运算)

    http://poj.org/problem?id=1753 题意:一个4*4的棋盘,只有黑和白两种棋子,每次翻转一个棋子,并且其四周的棋子也跟着翻转,求棋盘全为黑或全为白时所需的最少翻转次数. 思路 ...

  9. 关于express项目的创建与启动

    没有经常用,所以经常搞错, 创建express项目,需要新建一个文件夹名,这个文件名就是用来承载express的内容的, 好了.打开终端,cd至创建的文件夹之下. 也可以直接这样,如以下,admin为 ...

  10. 转载:Nginx负载均衡的5种策略

    nginx可以根据客户端IP进行负载均衡,在upstream里设置ip_hash,就可以针对同一个C类地址段中的客户端选择同一个后端服务器,除非那个后端服务器宕了才会换一个. nginx的upstre ...