洛谷 P2782 友好城市 排序 动态规划

news/2024/10/18 7:48:49/

题目描述

有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市。北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同。每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故。编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航道不相交的情况下,被批准的申请尽量多。

输入格式

第1行,一个整数N,表示城市数。

第2行到第n+1行,每行两个整数,中间用一个空格隔开,分别表示南岸和北岸的一对友好城市的坐标。

输出格式

仅一行,输出一个整数,表示政府所能批准的最多申请数。

输入输出样例
输入 #1
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
输出 #1
4

这道题看上去可以说一点思路都没有(反正蒟蒻是这样的)

可以看到他的输入是无序的,我们先按照他们的北岸的编号来排个序。然后来画个小图:

 我们用这些数表示他的北岸和南岸

假设是这样的:

北岸1-南岸3

北岸2-南岸5

北岸3-南岸1

北岸4-南岸2

北岸5-南岸4

 这个图有很多的交叉,所以我们不得不去舍去一些线。可以发现,把北岸1-南岸3和北岸2-南岸5舍去是最优解,这样能保留下3条边。

我们抽象一下,把上面的图的北岸排序后,南岸其实是这样的:

3 5 1 2 4

刚才做的,是把3和5舍去了,剩下的是1 2 4,也就构成了一个叫做“最长不下降子序列

好的,那么问题就抽象成了:在北岸有序的情况下,南岸的最长不下降子序列

求最长不下降子序列,首先想到的是O(n^2)的做法,可是n<=200000,n^2超时了,只有50分

50分做法:

# include <iostream>
# include <cstdio>
# include <algorithm>
# include <cstring>
using namespace std;
# define int long long
int n,maxn=-1;
int f[200005];
struct node{int nor,sou;
}map[200005]; 
bool cmp(node x,node y){return x.nor<y.nor;
}
signed main(){scanf("%lld",&n);for (int i=1;i<=n;i++){scanf("%lld%lld",&map[i].nor,&map[i].sou);f[i]=1;}sort(map+1,map+1+n,cmp);f[0]=1;for (int i=1;i<=n;i++){for (int j=1;j<i;j++){if (map[j].sou<=map[i].sou){f[i]=max(f[i],f[j]+1);}maxn=max(maxn,f[i]);}}printf("%lld",maxn);return 0;
}

(没啥可说的代码模板)

那么我们现在就要去优化,把j循环去了(最优)

还是画个小图,模拟下求最长不下降子序列的过程

这样一个序列,并创建一个数组,存储最长不下降子序列

首先,100加入子序列

再去考虑96,96如果加入子序列,100就会被踢掉,但96更小,所以保留96踢100

考虑334,他进入序列没问题

考虑25,他进入序列,就会把两个数都踢了,不划算,不要了

考虑162,他进来会把334踢了,可以

考虑131,他进来会把162踢了,没事

所以最后就是96 131

他这道题只问你最后的长度,具体的数不考虑,所以这样没问题

那么最后就用代码模拟这个过程就行

# include <iostream>
# include <cstdio>
# include <algorithm>
# include <cstring>
using namespace std;
# define int long long
int n,maxn;
int f[200005];
struct node{int nor,sou;
}map[200005]; 
bool cmp(node x,node y){return x.nor<y.nor;
}
int south[200005];
int left,right;
signed main(){scanf("%lld",&n);for (int i=1;i<=n;i++){scanf("%lld%lld",&map[i].nor,&map[i].sou);}sort(map+1,map+1+n,cmp);south[++maxn]=map[1].sou;for (int i=2;i<=n;i++){/*for (int j=1;j<i;j++){if (map[j].sou<=map[i].sou){f[i]=max(f[i],f[j]+1);}maxn=max(maxn,f[i]);}*/int ans=upper_bound(south+1,south+1+maxn,map[i].sou)-south;//寻找第一个>目标值的数 south[ans]=map[i].sou;if (ans>maxn){maxn++;}}printf("%lld",maxn);return 0;
}


http://www.ppmy.cn/news/533306.html

相关文章

卷积是什么

参考&#xff1a; 【官方双语】那么……什么是卷积&#xff1f;https://www.bilibili.com/video/BV1Vd4y1e7pj/ [建议看完] x.1 一维卷积 一维卷积&#xff0c;即对于两个向量的卷积&#xff0c;就是将向量翻转后&#xff0c;从前向后滑动&#xff0c;相乘再相加。 x.2 二维卷…

CAD迷你看图v4.4.3 for Mac 小巧而全面的CAD看图工具

Mac毒搜集到的CAD迷你看图Mac版是一款非常小巧、快速、方便的DWG看图工具 应用介绍 CAD迷你看图Mac版是一款非常小巧、快速、方便的DWG看图工具&#xff0c;cad迷你看图Mac版可脱离AutoCAD最快速、最方便浏览DWG和DXF图纸&#xff0c;支持二维或三维图纸&#xff0c;支持高清…

ISP-看图工具收集

背景 图像处理中经验需要看RAW/YUV/RGB等图像。记录下常用的看图工具。 名称功能备注YUView1.可以用来看单通道RAWImageJ1.看图并且可以分析图像的工具faststone image viewer1.可以用来4宫格对比图像

win10自带看图工具不见,修改注册表就出来了

win10自带看图工具不见了 1.按WinR打开运行&#xff0c;输入regedit打开注册表编辑器&#xff1b; win10自带看图工具不见了 最近有很多朋友遇到win10自带看图工具找不到了&#xff0c;怎么办&#xff1f;有的朋友发现win10自带的看图软件没了&#xff0c;有的人会去网上下载看…

win10自带看图工具找不到了咋办

最近有很多朋友遇到win10自带看图工具找不到了&#xff0c;怎么办&#xff1f;有的朋友发现win10自带的看图软件没了&#xff0c;有的人会去网上下载看图工具&#xff0c;其实我们并不需要&#xff0c;系统自带的看图工具我们是有办法调取出来的&#xff0c;废话不多说&#xf…

win10自带看图工具找不到了怎么办?

最近有很多朋友遇到win10自带看图工具找不到了&#xff0c;怎么办&#xff1f;有的朋友发现win10自带的看图软件没了&#xff0c;有的人会去网上下载看图工具&#xff0c;其实我们并不需要&#xff0c;系统自带的看图工具我们是有办法调取出来的&#xff0c;废话不多说&#xf…

一款简单而强大的TIF文件查看软件 -- IrfanView

文章目录 1 IrfanView官网2 什么是IrfanView3 IrfanView特性4 汉化5 安装包语汉化包下载 你有没有遇到过这种困扰&#xff0c;虽然Win10自带的几个图片查看器都支持TIF文件查看&#xff0c;但是当TIF文件体积超过百兆时&#xff0c;他们几个就显得比较吃力。 通常可以选择Photo…

推荐一款免费好用的Gerber查看软件

推荐一款免费好用的Gerber查看软件 软件大小&#xff1a;69.16MB 软件语言&#xff1a;中文、英文、中文繁体 软件类型&#xff1a;国产软件 / 辅助设计 运行环境&#xff1a;Win7, WinAll 授权方式&#xff1a;免费 下载地址&#xff1a;http://www.vayoinfo.net/gview_Downl…