Codeforces Round 809 (Div. 2)

发布时间 2023-12-12 18:29:42作者: 加固文明幻景

基本情况

A题秒了。

B题卡了很久,最后过了。

C来不及了。

B. Making Towers

Problem - B - Codeforces

卡题分析

最初想法

其实已经推出来下标差为奇数才能构成高塔了。

但是思维固化,认为这个问题就必须用LIS那类做法做,然后硬打了一个 \(\operatorname O(n^2)\)DP,然后就 TLE 了。

int a[N];
std::vector<int> tag[N];
long long F[N];

void solve()
{
	int n;
	std::cin >> n;
	for (int i = 1; i <= n; i++) tag[i].clear();
	for (int i = 1; i <= n; i++) std::cin >> a[i], tag[a[i]].push_back(i);
	for (int i = 1; i <= n; i++)
	{
		if (tag[i].empty())
		{
			std::cout << 0 << " ";
			continue;
		}
		long long ans = 1;
		for (int j = 0; j < tag[i].size(); j++)
		{
			F[j] = 1;
			for (int k = 0; k < j; k++)
			{
				if ((tag[i][j] - tag[i][k]) & 1)
					F[j] = std::max(F[j], F[k] + 1), ans = std::max(ans, F[j]);
			}
		}
		std::cout << ans << " ";
	}
	std::cout << std::endl;
}

但事实上,这个问题和LIS有一个巨大的差别。

LIS的传递性来源是当前单位比选择的单位大。

也就是说开头在前面的序列不一定是最长的:

1 6 3 4 5 7 9

从这个序列看显然:

6 7 9 < 3 4 5 7 9

但是这题,本身我存下标的时候,就是严格递增的啊啊!!!

而且,传递性是下标差为奇数,这玩意虽然不好证明越左边的肯定越好,但是也很不好反证,所以索性尝试直接从第一个开始算,然后相差不是奇数的就不算就行,严格来讲已经不算DP了,但这样就过了。

int a[N];
std::vector<int> tag[N];

void solve()
{
	int n;
	std::cin >> n;
	for (int i = 1; i <= n; i++) tag[i].clear();
	for (int i = 1; i <= n; i++)
	{
		std::cin >> a[i];
		if (tag[a[i]].empty())
		{
			tag[a[i]].push_back(i);
			continue;
		}
		if ((i - tag[a[i]].back()) & 1) tag[a[i]].push_back(i);
	}
	for (int i = 1; i <= n; i++)
	{
		if (tag[i].empty())
		{
			std::cout << 0 << " ";
			continue;
		}
		std::cout << tag[i].size() << " ";
	}
	std::cout << std::endl;
}

C. Qpwoeirut And The City

Problem - C - Codeforces

待补题。