[题解] 8.11考试 水渠

Posted biscuits0819

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解] 8.11考试 水渠相关的知识,希望对你有一定的参考价值。

题目描述

把n+m个点分为两列,第一列有n个点,第二列有m个点。

每一列的点的横坐标相同,给这些点连边,将这n+m个点全部连通,求所连边的最小总和。

输入格式

第一行四个整数n,m,x1,x2,分别表示第一列的点数,第二列的点数,第一列中点的横坐标,第二列中的点的横坐标。

第二行n个正整数y1[1],y1[2],...,y1[n],表示第一列中的点的纵坐标。

其中,第一个数表示第一个点的纵坐标,接下来的数表示当前点与前一个点的纵坐标差。

第三行有m个正整数,意义同上。

 

输出格式

一个实数,为边的最小总和,答案保留两位小数。

数据范围

n,m<=600000,所有点的纵坐标不超过10^8,x1<x2<2000.

输入样例

2 3 1 3

1 2

2 2 1

输出样例

7.24

思路解析

这道题自认为是今天的签到题(蒟蒻只会写签到题的题解了)。

可以证明一个点最多连四条边。

即与同列的前一个点和后一个点各连一条。

然后以该点的纵坐标作一条平行于x轴的虚线。

与另一列的虚线上第一个点和虚线下第一个点各连一条边。

可以证明这两个点之一肯定是另一列离这个点最近的点。

然后跑kruscal就行了。

(其实正解是DP,但既然kruscal卡常卡过了就不写DP了吧2333 (bmw))

 

赋上代码

#include<bits/stdc++.h>
#define inf 1030032399
using namespace std;
const int N=6e5+5;
int n,m,len,xI,xII,yI[N],yII[N],pa[N*2];
double ans,minn=inf;
struct node
  int x,y;double z;
  bool operator < (const node &mt)const 
    return z<mt.z;
  
f[N*4];
inline int read()
  int r=0,t=1,c=getchar();
  while(c<0||c>9) t=c==-?-1:1,c=getchar();
  while(c>=0&&c<=9) r=r*10+c-48,c=getchar();
  return r*t;

double dis(int x,int y)
  double sss=x,llf=y;
  return sqrt((double)(xII-xI)*(double)(xII-xI)+(llf-sss)*(llf-sss));

int Find(int now)
  if(now==pa[now]) return now;
  return pa[now]=Find(pa[now]);

void kruscal()
  int cnt=0;
  for(int i=1;i<=n+m;i++)
    pa[i]=i;
  for(int i=1;i<=len;i++)
    int zjy=Find(f[i].x),tlj=Find(f[i].y);
    if(zjy!=tlj)
      pa[zjy]=tlj;
      cnt++;ans+=f[i].z;
      if(cnt==n+m-1)
    return ;
    
  

int main()
  freopen("canal.in","r",stdin);
  freopen("canal.out","w",stdout);
  int x;
  n=read(),m=read(),xI=read(),xII=read();
  yI[1]=read();
  for(int i=2;i<=n;i++)
    x=read();
    yI[i]=yI[i-1]+x;
    f[++len]=(node)i-1,i,x*1.;
  
  yII[1]=read();
  for(int i=2;i<=m;i++)
    x=read();
    yII[i]=yII[i-1]+x;
    f[++len]=(node)i-1+n,i+n,x*1.;
  
  int now=0;
  for(int i=1;i<=n;i++)
    for(int j=now+1;j<=m;j++)
      if(yII[j]>=yI[i])
    break;
      now=j;
    
    if(now)
      f[++len]=(node)i,now+n,dis(yI[i],yII[now]);
    f[++len]=(node)i,now+n+1,dis(yI[i],yII[now+1]);
  
  sort(f+1,f+len+1);
  kruscal();
  printf("%.2f",ans);
  return 0;

洛谷博客

以上是关于[题解] 8.11考试 水渠的主要内容,如果未能解决你的问题,请参考以下文章

$NOIP 2016 Day1$ 模拟考试 题解报告

$NOIP 2018 Day2$ 模拟考试 题解报告

PAT(甲级)2019年春季考试题解

CCF计算机职业资格认证考试题解

HDU各种考试题题解

考试题解集合