1 条题解
-
0
为什么题解区只有一篇题解?我来写一篇。
称在输入数据中输入的点为顶点。可以确定,多边形上的每一个顶点一定都可以找到另一个顶点与它匹配,且匹配方案唯一。
由于多边形的周长很小,可以直接用数组存储多边形边上的每一个点。
一条光线从一点射向另一点可以看作在图上在这两点之间建无向边。我们可以用 dsu 维护两点的可到达性。如果两个顶点之间是联通的,那么这两个顶点就可以匹配。
把多边形逆时针转 ,这样光线会平行于坐标轴。将所有点以 为第一关键字, 为第二关键字排序尝试靠竖的光线连边,再将所有点以 为第一关键字, 为第二关键字排序尝试靠横的光线连边,这样我们就能找到所有匹配。
另外,光线在某些情况下可以从顶点中穿过去而不被接收,例如样例中从 号顶点射出的光线穿过了 号顶点。这种情况需要特判。具体方法就是求出顶点的朝向然后看顶点在这个朝向能不能接到光。
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define N 300010 #define INF 0x3f3f3f3f #define lowbit(x) (x&-x) #define pii pair<int,int> #define cpx complex<double> #define poly vector<ll> #define get(x) (x?x:n) int n,x,y,len[N],la; struct node{int x,y,v,idx;}a[N]; inline bool cmp(const node &n1,const node &n2){return (n1.x!=n2.x)?n1.x<n2.x:n1.y<n2.y;} inline bool cmp1(const node &n1,const node &n2){return (n1.y!=n2.y)?n1.y<n2.y:n1.x<n2.x;} inline void insert(){ ++la,a[la] = {x-y,x+y,-1,la}; } int dad[N],dep[N],f[N]; int find(const int &x){return (dad[x]==x?x:(dad[x] = find(dad[x])));} inline void merge(int x,int y){ x = find(x),y = find(y); if(x == y)return ; // printf("merging %d %d\n",x,y); if(dep[x]<dep[y])swap(x,y); dad[y] = x,dep[x] = max(dep[x],dep[y]+1); if(f[x]&&f[y])cout << f[x] << ' ' << f[y] << "\n"; else if(f[x]||f[y])f[x] += f[y]; } inline void solve(const int &op){ sort(a+1,a+la+1,op?cmp1:cmp); int last = 0; for(int i = 1;i <= la;++i){ if((op && a[i].y != a[i-1].y) || (!op && a[i].x != a[i-1].x))last = 0; if(a[i].v >= 0 && (a[i].v)!=op)continue; if(!last)last = a[i].idx; else merge(a[i].idx,last),last = 0; } } // 主函数 int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin >> n; for(int i = 1;i <= n;++i)cin >> x >> y,len[i] = x+y; int tmp = len[n]; for(int i = n;i >= 2;--i)len[i] = len[i]-len[i-1];len[1] = len[1] - tmp; x = 0,y = 0; for(int i = 1;i <= n;++i){ if(i & 1){// 动 x if(len[i] > 0){ for(int j = 0;j < len[i];++j)insert(),++x; a[la-len[i]+1].v = (len[get(i-1)]>0),f[la-len[i]+1] = get(i-1); }else{ for(int j = 0;j < -len[i];++j)insert(),--x; a[la+len[i]+1].v = (len[get(i-1)]<0),f[la+len[i]+1] = get(i-1); } }else{ if(len[i] > 0){ for(int j = 0;j < len[i];++j)insert(),++y; a[la-len[i]+1].v = (len[get(i-1)]>0),f[la-len[i]+1] = get(i-1); }else{ for(int j = 0;j < -len[i];++j)insert(),--y; a[la+len[i]+1].v = (len[get(i-1)]<0),f[la+len[i]+1] = get(i-1); } } } cout << (n>>1) << '\n'; for(int i = 1;i <= la;++i)dad[i] = i,dep[i] = 1; a[0] = {-INF,-INF,-INF,-INF}; solve(0),solve(1); return 0; }
- 1
信息
- ID
- 2774
- 时间
- 3000ms
- 内存
- 64MiB
- 难度
- 8
- 标签
- 递交数
- 18
- 已通过
- 5
- 上传者