1. 程式人生 > 其它 >【CF4D Mysterious Present】題解

【CF4D Mysterious Present】題解

題目連結

題目

Peter decided to wish happy birthday to his friend from Australia and send him a card. To make his present more mysterious, he decided to make a chain. Chain here is such a sequence of envelopes A A A = { a1,a2,...,an a_{1},a_{2},...,a_{n} a1​,a2​,...,an​ }, where the width and the height of the i i i -th envelope is strictly higher than the width and the height of the (i−1) (i-1) (i−1) -th envelope respectively. Chain size is the number of envelopes in the chain.

Peter wants to make the chain of the maximum size from the envelopes he has, the chain should be such, that he'll be able to put a card into it. The card fits into the chain if its width and height is lower than the width and the height of the smallest envelope in the chain respectively. It's forbidden to turn the card and the envelopes.

Peter has very many envelopes and very little time, this hard task is entrusted to you.

給出一個限制 (w,h)(w,h)(w,h) 和 nnn 個物品的二維資訊(wi,hi)(w_i,h_i)(wi​,hi​)

求物品二維都滿足 wi>w,hi>hw_i>w,h_i>hwi​>w,hi​>h 的前提下的最長二維嚴格上升子序列以及其長度(wi>wi−1,hi>hi−1(w_i>w_{i-1},h_i > h_{i-1}(wi​>wi−1​,hi​>hi−1​ )

如果找不到任何一個物品滿足條件 只需輸出一行 0

思路

先排除掉不符合的,然後按x軸排序,接著按y軸做最長上升子序列即可。

上升子序列只需要打暴力的,什麼二分單調佇列樹狀陣列優化都不用。

總結

這題本質上就是最長上升子序列模板,並不需要太多技巧。

這種題認真看題,打時認真點即可。

也可以順手複習一下 \(O(n\log n)\) 方法。

Code

// Problem: CF4D Mysterious Present
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF4D
// Memory Limit: 62 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 5010
struct node
{
	int x, y, id; 
}a[N]; 
int n, m, i, j, k; 
int w, h, dp[N], pre[N]; 

bool cmp(node x, node y)
{
	if(x.x==y.x) return x.y<y.y; 
	return x.x<y.x; 
}

void dfs(int x)
{
	if(pre[x]) dfs(pre[x]); 
	printf("%lld ", a[x].id); 
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	n=read(); w=read(); h=read(); 
	for(i=1; i<=n; ++i)
	{
		a[i].x=read(); a[i].y=read(); 
		if((a[i].x<=w)||(a[i].y<=h)) continue; 
		// printf("0"); 
		a[++m].x=a[i].x; a[m].y=a[i].y; a[m].id=i; 
	}
	sort(a+1, a+(n=m)+1, cmp); 
	for(i=1, m=0; i<=n; ++i)
	{
		dp[i]=1; pre[i]=0; 
		for(j=1; j<=n; ++j)
			if(a[i].x>a[j].x&&a[i].y>a[j].y)
				if(dp[j]+1>dp[i])
					dp[i]=dp[j]+1, pre[i]=j; 
		if(dp[i]>m) m=dp[i], k=i; 
	}
	printf("%lld\n", m); 
	if(m) dfs(k); 
	return 0; 
}