三维(多维)偏序最大上升子序列问题(不用cdq/kdtree实现接近o(nlgn)的简单算法)

三维(多维)偏序最大上升子序列问题(不用cdq/kdtree实现接近o(nlgn)的简单算法)

一般最大上升子序列问题

对于一般最大上升子序列问题而言可以定义为二维的。其中一个维度方向是依据具体数据类型的比较(可能有多种重载),例如整型数依照大小,字符依照ASCII码,复数依照模的大小。第二个维度一般是隐藏的自然顺序(输入顺序)或其他。

多维最大上升子序列问题

对于二维问题不再赘述,其他地方写的非常清楚,这里主要讲一下高维问题,具体问题如下(数算课的作业。。)
某种数据类型为p{sl,sr},其中sl和sr都是非负整数,顺序输入n个数据,求出这n个数据中满足“总体进步”的子序列的最大长度。“总体进步”指在这个子序列中对于任意p[i],p[j],若j>i,则p[j].sl>=p[i].sl且p[j].sr>=p[i].sr。

问题分析
在上述题目中,其实就是一个求三维偏序的最大长度问题。其中三维偏序分别是《sl,>=》《sr,>=》《i(input sequence),>》

O(n^2)算法(动态规划)
思路同二维问题的O(n^2)算法一样,记输入的数据数组为A,还需要一个一个长度和A相同的的数组D,D[i]和A[i]一一对应,用来记录以A[i]结尾的最大上升子序列的长度。

假如我们已经得到D[0]到D[k],现在求解D[k+1],就应该遍历D[0]到D[k],找出满足A[k]对A[j]是“总体进步”的j1、j2、……再找到D[j1]、D[j2]、……中的最大值D[j],则D[k+1]=D[j]+1。

其中D[0]=1,在求出D[0]到D[n]后,D中元素的最大值就是所求的最大上升子序列的长度。

总结一下,在这个方法中高维问题和二维问题的差别在于对”比较“的定义,二维问题中,因为p[i]就是一个数,“p[i]>=p[j]“就是“p[i]>=p[j]”。而在三维问题中“p[i]>=p[j]“等价于“p[i].sl>=p[j].sl&&p[i].sr>=p[j].sr”。

换句话说,只需要将比较运算符重载一下,就可以将二维问题的解法直接套用在高维问题中。

code:

#include<iostream>
using namespace std;
struct photo {
   
	int sl;
	int sr;
	photo() {
   
		sl = 0; sr = 0; 
	}
};

int main()
{
   
	int  n;
    cin >> n;
		photo p[50000];	
		int d[50000] = {
    0 };
		for (int j = 0; j < n; j++) {
   
			cin >> p[j].sl >> p[j].sr;
			int ll = 0;
			if (!j) {
   
				d[0] = 1;
			}
			else {
   
				for (int k = 0; k < j; k++) {
   
					if (p[k].sl <= p[j].sl && p[k].sr <= p[j].sr)ll = max(ll, d[k])
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值