原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045E.html

4K码量构造题,CF血腥残暴!

题解

首先,如果所有点颜色相同,那么直接连个菊花搞定。

然后我们建个凸包。

如果凸包上有大于2段颜色(就是至少四段),比如这样

那么必然无解。

否则就只有一段颜色或者两段颜色:

这里我们先不管这个,考虑一个三角形的构造。

考虑三角形三个顶点颜色不全相同的情况,例如:

(两个白点的情况是等价的)

假如三角形区域内没有白点,那么直接全部连到其中一个黑点就好了。

否则假设里面有一个白点:

那么我们将白顶点连上这个中间的白点(将红色边加入最终答案),把原三角形划分成3个子问题递归求解即可。

回到原问题:

如果凸包上只有一种颜色,那么在里面找一个白点(因为已经排除全部都是黑点的情况了,所以必然有白点),如下图一样将红色边相连,按照红/黑色边将凸包三角划分成子问题解决即可:

如果凸包上有两种颜色,那么就类似地:

划分集合的暴力枚举点判定是否在三角形内就好了。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1005;
int n;
struct Point{
int x,y;
Point(){}
Point(int _x,int _y){
x=_x,y=_y;
}
friend Point operator + (Point A,Point B){
return Point(A.x+B.x,A.y+B.y);
}
friend Point operator - (Point A,Point B){
return Point(A.x-B.x,A.y-B.y);
}
friend bool operator == (Point A,Point B){
return A.x==B.x&&A.y==B.y;
}
friend bool operator != (Point A,Point B){
return A.x!=B.x||A.y!=B.y;
}
}O;
int cross(Point A,Point B){
return A.x*B.y-B.x*A.y;
}
int cross(Point A,Point B,Point C){
return cross(B-A,C-A);
}
int Dot(Point A,Point B){
return A.x*B.x+A.y*B.y;
}
int Dis(Point A,Point B){
return Dot(A-B,A-B);
}
struct civ{
Point p;
int c,id;
civ(){}
civ(Point _p,int _c,int _id){
p=_p,c=_c,id=_id;
}
};
civ Get_civ(int id){
Point p;
p.x=read(),p.y=read();
int c=read();
return civ(p,c,id);
}
vector <civ> p,con;
bool cmpO(Point a,Point b){
return a.y!=b.y?a.y<b.y:a.x<b.x;
}
bool cmpAngle_civ(civ a,civ b){
int c=cross(O,a.p,b.p);
return c?c>0:Dis(O,a.p)<Dis(O,b.p);
}
vector <civ> Get_Convex(vector <civ> p){
vector <civ> st(0);
int n=p.size();
for (int i=1;i<n;i++)
if (!cmpO(p[0].p,p[i].p))
swap(p[0],p[i]);
O=p[0].p;
sort(p.begin()+1,p.end(),cmpAngle_civ);
for (int i=0;i<n;i++){
while (st.size()>1&&cross(st[st.size()-2].p,st.back().p,p[i].p)<=0)
st.pop_back();
st.push_back(p[i]);
}
return st;
}
int check_same(){
for (int i=1;i<n;i++)
if (p[i].c!=p[0].c)
return 0;
return 1;
}
int check_inside(Point A,Point B,Point C,Point P){
if (P==A||P==B||P==C)
return 0;
int S1=abs(cross(A,B,C));
int S2=abs(cross(P,A,B))+abs(cross(P,B,C))+abs(cross(P,C,A));
return S1==S2;
}
vector <civ> get_inside(Point A,Point B,Point C,vector <civ> S){
static vector <civ> res;
res.clear();
for (auto v : S)
if (check_inside(A,B,C,v.p))
res.push_back(v);
return res;
}
vector <pair <int,int> > ans;
void solve(civ A,civ B,civ C,vector <civ> S){
int flag=0;
civ p;
for (auto c : S)
if (c.c!=A.c){
flag=1,p=c;
break;
}
if (!flag){
for (auto c : S)
ans.push_back(make_pair(A.id,c.id));
return;
}
ans.push_back(make_pair(C.id,p.id));
solve(A,B,p,get_inside(A.p,B.p,p.p,S));
solve(C,p,A,get_inside(C.p,p.p,A.p,S));
solve(C,p,B,get_inside(C.p,p.p,B.p,S));
}
int main(){
n=read();
for (int i=1;i<=n;i++)
p.push_back(Get_civ(i));
con=Get_Convex(p);
int cnt=con[0].c^con.back().c;
for (int i=1;i<con.size();i++)
cnt+=con[i-1].c^con[i].c;
if (cnt>2)
return puts("Impossible"),0;
ans.clear();
if (cnt==0){
if (check_same()){
printf("%d\n",n-1);
for (int i=1;i<n;i++)
printf("%d %d\n",0,i);
return 0;
}
for (int i=1;i<con.size();i++)
ans.push_back(make_pair(con[i-1].id,con[i].id));
civ mid;
for (auto c : p)
if (c.c!=con[0].c){
mid=c;
break;
}
solve(con[0],con.back(),mid,get_inside(con[0].p,con.back().p,mid.p,p));
for (int i=1;i<con.size();i++)
solve(con[i-1],con[i],mid,get_inside(con[i-1].p,con[i].p,mid.p,p));
}
else {
vector <civ> _con(0);
int stco=con[0].c^1,i;
int m=con.size();
for (i=0;;i=(i+1)%m)
if (con[i].c==stco){
_con.push_back(con[i]);
if (con[(i+1)%m].c!=stco)
break;
}
stco^=1;
for (i=(i+1)%m;;i=(i+1)%m)
if (con[i].c==stco){
_con.push_back(con[i]);
if (con[(i+1)%m].c!=stco)
break;
}
con=_con;
for (i=0;i<m;i++)
if (con[i].c!=con[(i+1)%m].c)
break;
int b=i;
for (int i=0;i<b;i++)
ans.push_back(make_pair(con[i].id,con[i+1].id));
for (int i=b+1;i<m-1;i++)
ans.push_back(make_pair(con[i].id,con[i+1].id));
b++;
for (int i=0;i<b-1;i++)
solve(con[i],con[i+1],con[b],get_inside(con[i].p,con[i+1].p,con[b].p,p));
for (int i=b;i<m-1;i++)
solve(con[i],con[i+1],con[0],get_inside(con[i].p,con[i+1].p,con[0].p,p));
}
printf("%d\n",(int)ans.size());
for (auto e : ans)
printf("%d %d\n",e.first-1,e.second-1);
return 0;
}

  

Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包的更多相关文章

  1. Codeforces Beta Round #1 C. Ancient Berland Circus 计算几何

    C. Ancient Berland Circus 题目连接: http://www.codeforces.com/contest/1/problem/C Description Nowadays a ...

  2. Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...

  3. 计算几何---凸包问题(Graham/Andrew Scan )

    概念 凸包(Convex Hull)是一个计算几何(图形学)中的概念.用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的.严谨的定义和相关概念参 ...

  4. 计算几何-凸包-toleft test

    toLeftTest toLeftTest是判断一个点是否在有向直线左侧的算法. 当点s位于向量pq左侧时,toLeftTest返回true.当点s位于向量pq右侧时,toLeftTest返回fals ...

  5. 计算几何-凸包算法 Python实现与Matlab动画演示

    凸包算法是计算几何中的最经典问题之一了.给定一个点集,计算其凸包.凸包是什么就不罗嗦了 本文给出了<计算几何——算法与应用>中一书所列凸包算法的Python实现和Matlab实现,并给出了 ...

  6. Codeforces 1383D - Rearrange(构造)

    Codeforces 题面传送门 & 洛谷题面传送门 一道不算困难的构造,花了一节英语课把它搞出来了,题解简单写写吧( 考虑从大往小加数,显然第三个条件可以被翻译为,每次加入一个元素,如果它所 ...

  7. Codeforces 549B. Looksery Party[构造]

    B. Looksery Party time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  8. 【BZOJ-1069】最大土地面积 计算几何 + 凸包 + 旋转卡壳

    1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 2707  Solved: 1053[Submit][Sta ...

  9. codeforces 323A. Black-and-White Cube 构造

    输入n 1 <= n <= 100 有一个n * n * n 的立方体,由n ^ 3 个1 * 1 * 1 的单位立方体构成 要用white 和 black 2种颜色来染这n ^ 3个立方 ...

随机推荐

  1. MySQL——修改一个表的自增值

    语句 alter table <table name> auto_increment=<value>; 示例 mysql; Query OK, rows affected (0 ...

  2. <三>企业级开源仓库nexus3实战应用–使用nexus3配置maven私有仓库

    一两个星期之前,你如果在我跟前说起私服的事情,我大概会绕着你走,因为我对这个东西真的一窍不通.事实上也正如此,开发同学曾不止一次的跟我说公司的私服版本太旧了,许多新的依赖编译之后不会从远程仓库自动缓存 ...

  3. A Reliability-Aware Network Service Chain Provisioning With Delay Guarantees in NFV-Enabled Enterprise Datacenter Networks

    文章名称:A Reliability-Aware Network Service Chain Provisioning With Delay Guarantees in NFV-Enabled Ent ...

  4. Hbase CMS GC 调优。

    export HBASE_OPTS="-XX:+UseConcMarkSweepGC" export HBASE_LOG_DIR=/app/hbase/logexport HBAS ...

  5. SpringCloud笔记三:Eureka服务注册与发现

    目录 什么是Eureka? Eureka注册的三大步 第一步,引用Maven 第二步,配置yml 第三步,开启Eureka注解 新建Eureka子项目 把provider子项目变成服务端 Eureka ...

  6. C++回顾day02---<运算符重载>

    一:运算符重载的限制 (一)可以重载的运算符: + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << > ...

  7. Aurora — 一个在 MSOffice 内输入 LaTeX 公式的很好用插件

    from http://blog.csdn.net/GarfieldEr007/article/details/51452986 工具名称:Aurora2x  (下载) 压缩包内有详细的安装说明. 刚 ...

  8. 报文段、协议、MAC地址

  9. 5.CentOS7安装mariadb

    MariaDB 和 MySQL 使用是一样的,二者只要安装一个就行了 MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司 ...

  10. 如何让vue项目兼容IE浏览器

    一般来说项目开发到后期都需要做各种兼容性处理例如:360.IE9以上.QQ浏览器....等等 那么现在来介绍一个工具 babel-cli 跟 babel-preset-es2015 babel-cli ...