https://codeforces.com/contest/958/problem/E3

当没有三点共线时,任意一个这样的点集都是保证可以找到答案的,(考虑任意一种有相交的连线方案,一定可以将其中两条相交的连线改成不相交的,并使得连线的总长度变小;显然连线的总长度最小的方案一定存在,则这种方案一定没有连线相交)

因此可以有一个分治做法:先在当前点集中找出最左、最下的点,找出一个点与其配对,使得以这两点间连线所在的直线划分开点集后,两边各自都满足白点数等于黑点数;显然一定能找到这个与其配对的点

找的方法就是其他点以选出这个点为中心做极角排序,然后双指针

复杂度n^2*log

本来以为分治时可以随便找出一个点,但事实上这样不对的,举个例子:

(以A2为选出点,则找不到配对点)

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace X
{
struct Point
{
int x,y;
Point(int x=,int y=):x(x),y(y){}
};
typedef Point Vec;
Vec operator+(const Vec& a,const Vec& b)
{
return Vec(a.x+b.x,a.y+b.y);
}
Vec operator-(const Vec& a,const Vec& b)
{
return Vec(a.x-b.x,a.y-b.y);
}
int dcmp(int x)
//正为1,负为-1,0为0
{
if(x==) return ;
return x<?-:;
}
bool operator==(const Vec& a,const Vec& b)
//判向量相等
{
return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;
}
double cross(const Vec& a,const Vec& b)
//叉积
{
return a.x*b.y-a.y*b.x;
}
};
using namespace X;
Point p[];
int an[];
int d[],tmp[];
int n;
double ang[];
bool vis[];
bool c1(int a,int b)
{
return ang[a]<ang[b];
}
bool c2(int a,int b)
{
return p[a].x<p[b].x||(p[a].x==p[b].x&&p[a].y<p[b].y);
}
void solve(int l,int r)
{
if(r<l) return;
swap(*min_element(d+l,d+r+,c2),d[l]);
int i;
for(i=l+;i<=r;i++)
ang[d[i]]=atan2(p[d[i]].y-p[d[l]].y,p[d[i]].x-p[d[l]].x);
sort(d+l+,d+r+,c1);
int len=r-l,a[]={,},nl,nr;
for(nl=l+,nr=l;nl<=r;nl++)//包含(nl,nr]的点,nl自身与l相连
{
while(nr<nl||(nr-nl+<len&&cross(p[d[(nr-l)%len+l+]]-p[d[l]],p[d[nl]]-p[d[l]])<))
{
++nr;
a[d[(nr-l-)%len+l+]<=n]++;
}
a[d[nl]<=n]--;
if(int(d[nl]<=n)+(d[l]<=n)==&&a[]==a[]) break;
}
if(d[l]<=n) an[d[l]]=d[nl];
else an[d[nl]]=d[l];
for(i=l+;i<=r;i++)
vis[i]=;
vis[nl]=;
tmp[]=;
for(i=nl+;i<=nr;i++)
{
vis[(i-l-)%len+l+]=;
tmp[++tmp[]]=d[(i-l-)%len+l+];
}
int t1=l;
for(i=l+;i<=r;i++)
if(!vis[i])
{
d[++t1]=d[i];
}
int t2=t1;
for(i=;i<=tmp[];i++)
d[++t2]=tmp[i];
solve(l+,t1);solve(t1+,t2);
}
int main()
{
int i;
while(scanf("%d",&n)==)
{
for(i=;i<=*n;i++) scanf("%d%d",&p[i].x,&p[i].y);
for(i=;i<=*n;i++) d[i]=i;
solve(,*n);
for(i=;i<=n;i++) printf("%d\n",an[i]-n);
}
return ;
}

双倍经验:https://vjudge.net/problem/UVA-1411

Guard Duty (hard) Codeforces - 958E3 || uva 1411的更多相关文章

  1. Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化

    https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...

  2. 【UVA 1411】 Ants (KM)

    Young naturalist Bill studies ants in school. His ants feed onplant-louses that live on apple trees. ...

  3. UVA 1411 - Ants(二分图完美匹配)

    UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...

  4. uva 1411 Ants (权值和最小的完美匹配---KM算法)

    uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...

  5. poj 3565 uva 1411 Ants KM算法求最小权

    由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...

  6. uva 1411 Ants

    题意: 一个平面上有n个黑色的点,n个白色的点,要求黑色的点与白色点之间一一配对,且线段之间不相交. 思路: 线段不相交并不好处理,想了很久想不出,所以看了蓝书的讲解. 一个很明显的结论是,不相交的线 ...

  7. 【uva 1411 Ants蚂蚁们】

    题目大意: ·给你一个n,表示输入n个白点和n个黑点(输入每一个点的坐标).现在需要将各个白点和各个黑点一一用线段连接起来,需要满足这些线段不能够相交. ·特色: 我们如何保证线段间不相交. ·分析: ...

  8. CF 958E2. Guard Duty (medium)

    这道题是昨天linkfqy dalao上课讲的一道题 当时他讲的时候就想到了一种玄学的搞法,然后不敢相信自己切掉了 没想到后来CHJ dalao也想到了这种算法,然后发现是对的 后来10min就切掉了 ...

  9. UVa 1411 Ants(分治)

    https://vjudge.net/problem/UVA-1411 题意:n只蚂蚁和n颗苹果树,一一配对并且不能交叉. 思路:这就是巨人与鬼的问题.用分治法就行了. #include<ios ...

随机推荐

  1. Codeforces Round #254 (Div. 2) A. DZY Loves Chessboard —— dfs

    题目链接: http://codeforces.com/problemset/problem/445/A 题解: 这道题是在现场赛的最后一分钟通过的,相当惊险,而且做的过程也很曲折. 先是用递推,结果 ...

  2. java反射技术实例

    java反射技术实例​1. [代码][Java]代码     package com.gufengxiachen.java.reflectiontest; public class Person {p ...

  3. CentOS6.5 yum源设置

    在安装完CentOS后一般需要修改yum源,才能够在安装更新rpm包时获得比较理想的速度. 国内比较快的有163源.sohu源.这里以163源为例子. 1. cd /etc/yum.repos.d 2 ...

  4. BZOJ2006:超级钢琴(ST表+堆求前K大区间和)

    Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度 ...

  5. yolo-开源数据集coco kitti voc

    1.kitti数据集(参考博客:https://blog.csdn.net/jesse_mx/article/details/65634482  https://blog.csdn.net/baoli ...

  6. atexit函数详解

    对C语言有所了解的人都知道main函数是整个程序的入口,但是其实不然,在内核中可以使用链接器来设置程序的开始地方.当内核使⽤⼀个exec函数执⾏C程序时,在调⽤main函数之前先调⽤⼀个特殊的启动例程 ...

  7. 快速沃尔什变换(FWT)学习笔记 + 洛谷P4717 [模板]

    FWT求解的是一类问题:\( a[i] = \sum\limits_{j\bigoplus k=i}^{} b[j]*c[k] \) 其中,\( \bigoplus \) 可以是 or,and,xor ...

  8. ubuntu下使用锐捷校园网

    前言           以下内容是个人学习之后的感悟,转载请注明出处~ 1.首先下载锐捷Linux版本,然后解压缩后,有个rjsupplicant.sh这个脚本文件,于是按照README做了,终端中 ...

  9. asp.net中FileUpload得到上传文件的完整路径

    asp.net中FileUpload得到上传文件的完整路径 Response.Write("完整路径:" + Server.MapPath(FileUpload1.PostedFi ...

  10. Python2.7 urlparse学习

    urlparse模块主要是把url拆分为6部分,并返回元组.并且可以把拆分后的部分再组成一个url.主要有函数有urljoin.urlsplit.urlunsplit.urlparse等. urlpa ...