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;
}
0SGU 128 snake (&& ZOJ 3521) 尺取,排序二叉树,线段树 难度:2的更多相关文章
- 【BZOJ4552】排序(线段树,二分答案)
[BZOJ4552]排序(线段树,二分答案) 题面 BZOJ 题解 好神的题啊 直接排序我们做不到 怎么维护? 考虑一下,如果我们随便假设一个答案 怎么检验它是否成立? 把这个数设成\(1\),其他的 ...
- 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)
2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...
- ZOJ 3521 Fairy Wars oj错误题目,计算几何,尺取法,排序二叉树,并查集 难度:2
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3521 ATTENTION:如果用long long 减小误差,这道题只能用 ...
- ZOJ 1610 Count the Colors (线段树区间更新)
题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...
- ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)
ZOJ 3597 题意是说有n把枪,有m个靶子,每把枪只有一发子弹(也就是说一把枪最多只能打一个靶子), 告诉你第 i 把枪可以打到第j个靶, 现在等概率的出现一个连续的P把枪,在知道这P把枪之后,你 ...
- ZOJ 1859 Matrix Searching(二维线段树)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1859 Matrix Searching Time Limit: 10 Seco ...
- zoj 1610 Count the Colors(线段树延迟更新)
所谓的懒操作模板题. 学好acm,英语很重要.做题的时候看不明白题目的意思,我还拉着队友一块儿帮忙分析题意.最后确定了是线段树延迟更新果题.我就欣欣然上手敲了出来. 然后是漫长的段错误.... 第一次 ...
- [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树
Brief Description DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列. 现在他想支持两种操作: 0, l, r: 将a[l..r]原地升序排序. 1, l, r: 将a ...
- bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
随机推荐
- linux提示usb_serial_generic_write_bulk_callback - urb stoped: -32
1.环境: 上位机:ubuntu16.04 Linux jello 4.4.0-89-generic #112-Ubuntu SMP Mon Jul 31 19:38:41 UTC 2017 x86_ ...
- IntelliJ IDEA 在运行web项目时部署的位置
在idea中运行tomcat,把项目部署到其中,运行起来,去tomcat目录下去看,根本找不到部署的项目,那么项目是怎么运行的? 在idea中配置的tomcat,在运行时idea不会把项目放到该路径下 ...
- Wannafly14挑战赛 C(tarjan缩点)题解
题目:牛客题目链接 思路:这道题有点像这道题 先缩点,缩完之后判断一下整个强连通分量入度是不是0,如果是的话向ans压入该强连通分量最小的那个值.最后排序一下ans输出就行了. 思路一下就想到了,就是 ...
- c#进阶之Delegate
委托是什么?答:委托是一种类型 等同与 一个class类,继承System.MulticastDelegate,但mult....gate是一个特殊类,不能够派生 委托的调用,如何去使用 1/委托 ...
- Unity3D学习笔记(三):V3、运动、帧率、OnGUI
盯着看:盯住一个点 transform.LookAt(Vector3 worldPosition); using System.Collections; using System.Collection ...
- Python简单做二维统计图
先上一张效果图: 以上图是一段时间内黄金价格的波动图. 代码如下: import datetime as DT from matplotlib import pyplot as plt from ma ...
- hdu 5525 Product 数论算贡献
Product Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Proble ...
- [CentOS_7.4]Linux编译安装mono环境
一 安装mono 安装过程: 下载mono安装源,配置,编译,安装,设置环境变量. # wget http://download.mono-project.com/sources/mono/mono- ...
- const 学习笔记
#include<stdlib.h> #include<iostream> using namespace std; int main(){ // const 仅仅起到是否为常 ...
- Codeforces 918C - The Monster
918C - The Monster 思路1: 右键在新窗口打开图片 代码: #include<bits/stdc++.h> using namespace std; #define ll ...