Description
教主上电视了,但是蔚蓝城郊区沿河的村庄却因电缆线路老化而在直播的时候停电,这让市长SP先生相当的愤怒,他决定重修所有电缆,并改日播放录像,杜绝此类情况再次发生。
河流两旁各有n,m个村庄,每个村庄可以用二维坐标表示,其中河流一旁的村庄横坐标均为x1,河流另一旁的村庄横坐标均为x2。由于地势十分开阔,任意两个村庄可以沿坐标系直线修建一条电缆连接,长度即为两村庄的距离。要修建若干条电缆,使得任意两个村庄都可以通过若干个有电缆连接的村庄相连。
因为修建的经费与长度成正比,SP市长当然希望所花的钱越少越好,所以他希望你来帮助他设计一套方案,使得电缆总长度最小,并告诉所需要的电缆总长度。
Solution
这题贪心的想一下,即可优化成4nlogn的DP;
当然,用DP优化一下,即可变成O(nlogn)的,先打混排序,
设两个f,g一个表示下面联通了,一个表示还未联通,互相转移;
复杂度: O(nlog(n))
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define sqr(q) ((q)*(q))
using namespace std;
typedef double db;
typedef long long LL;
const int N=600100;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,n1;
LL y[N],yy[N],b0,x1,x2;
struct qqww
{
db v;int x,y;
}b[N*4];
int g[N*2];
db ans;
bool PX(qqww q,qqww w){return q.v<w.v;}
int gf(int q){return g[q]=(g[q]==q?q:gf(g[q]));}
int main()
{
int q;
read(n),read(n1),x1=read(q),x2=read(q);
fo(i,1,n)y[i]=y[i-1]+read(q);
fo(i,1,n1)yy[i]=yy[i-1]+read(q);
fo(i,2,n)b[++b0].v=abs(y[i]-y[i-1]),b[b0].x=i,b[b0].y=i-1;
fo(i,2,n1)b[++b0].v=abs(yy[i]-yy[i-1]),b[b0].x=i+n,b[b0].y=i+n-1;
q=1;
fo(i,1,n)if(y[i]>=yy[q])
{
while(q<n1&&yy[q+1]<=y[i])q++;
b[++b0].v=sqrt(sqr(x2-x1)+sqr(yy[q]-y[i])),b[b0].x=i,b[b0].y=q+n;
}
q=1;
fo(i,1,n1)if(y[q]<=yy[i])
{
while(q<n&&y[q+1]<=yy[i])q++;
b[++b0].v=sqrt(sqr(x2-x1)+sqr(yy[i]-y[q])),b[b0].x=i+n,b[b0].y=q;
}
sort(b+1,b+1+b0,PX);
fo(i,1,n+n1)g[i]=i;
q=0;
fo(i,1,b0)
{
if(q==n+n1-1)break;
int x=gf(b[i].x),y=gf(b[i].y);
if(x!=y)
{
q++;
ans+=b[i].v;
g[x]=y;
}
}
printf("%.2lf\n",ans);
return 0;
}