航线设计

来源:互联网 发布:sql语言的编写器 编辑:程序博客网 时间:2024/04/27 22:41

【训练题】航线设计
时间限制:1秒 内存限制:64M
【问题描述】

  有一个国家被一条河划分为南北两部分,在南岸和北岸总共有N对城镇,每一城镇在对岸都有唯一的友好城镇。任何两个城镇都没有相同的友好城镇。每一对友好城镇都希望有一条航线来往。于是他们向政府提出了申请。由于河终年有雾。政府决定不允许有任两条航线交叉(如果两条航线交叉,将有很大机会撞船)。

  你的任务是写一个程序来帮政府官员决定他们应拨款兴建哪些航线以使得没有出现交叉的航线最多。

【输入格式】

  第一行一个整数N,表示分布在河两岸的城镇对数。接下来的N行每行有两个由空格分隔的正数C,D(C、D<=10^9〉,描述每一对友好城镇沿着河岸与西边境线的距离,C表示北岸城镇的距离而D表示南岸城镇的距离。在河的同一边,任何两个城镇的位置都是不同的。

【输出格式】

  在安全条件下能够开通的最大航线数目。

【输入样例】

7
22 4
2 6
10 3
15 12
9 8
17 17
4 2

【输出样例】

4

【数据范围】

  1<=N<=500000

这道题是一道明显的动态规划,但由于n过大所以需要优化(难点就在优化),d[k]表示建k个桥最后一个桥的最小编号。通过分析可以发现d是一个递增数组,所以可以用二分来优化。

详细代码如下:

#include<iostream>#include<cstdlib>#include<cstdio>#include<algorithm>using namespace std;const int maxn=500005;const int inf=200000000;struct shu{    int w,v;    friend bool operator <(shu a,shu b)    {        return a.w<b.w;    }}a[maxn];int d[maxn],n;//d[i],建i个桥最后一个桥最小的编号。 int main(){    //freopen("in.txt","r",stdin);    scanf("%d",&n);    for(int i=1;i<=n;i++)    scanf("%d%d",&a[i].w,&a[i].v);    sort(a+1,a+1+n);    d[0]=0;    d[1]=a[1].v;    int k=1;    for(int i=2;i<=n;i++)    {        if(d[k]<a[i].v) d[++k]=a[i].v;        else         {            int A=0,B=k;            while(A<=B)            {                int C=(A+B)>>1;                if(d[C]<a[i].v&&d[C+1]>=a[i].v)                {                    d[C+1]=a[i].v;                    break;                }                if(d[C]>a[i].v) B=C-1;                if(d[C+1]<a[i].v) A=C+1;            }        }    }    printf("%d",k);    return 0;}
1 0
原创粉丝点击