【题意】给定坐标系中n个点的坐标(范围[0,10^6]),求一种 [ 连边形成链后总长度<=2.5*10^9 ] 的方案。n<=10^6。
【算法】思维题(分块思想)
【题解】将这个10^6*10^6的矩阵划分为1000个10^3*10^6的矩阵,第奇数个矩阵内部按y升序连边,第偶数个矩阵内部按y降序连边,两个矩阵之间就直接连边。
1.到达每个点横坐标要移动10^3,总距离10^9。
2.每个矩阵内部纵坐标要移动10^6,总距离10^9。
3.矩阵之间的连边,每次最长2*10^3,总距离2*10^6。
所以总距离为2*10^9+2*10^6,满足要求。
排序的实现和分块类似,复杂度O(n log n)。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int read(){ char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t; } const int maxn=1000010; struct cyc{int x,y,id;}a[maxn]; int n; bool cmp(cyc a,cyc b){return a.x<b.x||(a.x==b.x&&a.y<b.y);} int main(){ n=read(); for(int i=1;i<=n;i++){ a[i].x=read()/1000; a[i].y=read(); if(a[i].x%2)a[i].y=-a[i].y; a[i].id=i; } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++)printf("%d ",a[i].id); return 0; }