P3364 Cool loves touli

考虑 DP。

我们令 ai,bi,ci,dia_i,b_i,c_i,d_i 为每名英雄的四个属性,顺序如输入格式所描述。

显然有 fi=maxjaj<aidjbicjdifj+1f_i = \max \limits_{j|a_j<a_i \land d_j \leq b_i\land c_j \leq d_i} f_j + 1

\land 是逻辑与运算符。

经典的三维偏序,CDQ 分治优化 DP 即可。时间复杂度 O(nlog2n)O(n \log^2 n)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <cassert>
#include <vector>
using namespace std;

const int N = 1e6 + 5;

class Bit
{
public:
	int tr[N];
	int lowbit(int x)
	{
		return x & -x;
	}
	void ins(int x, int v)
	{
		while (x < N)
		{
			tr[x] = max(tr[x], v);
			x += lowbit(x);
		}
	}
	int query(int x)
	{
		int res = 0;
		while (x)
		{
			res = max(res, tr[x]);
			x -= lowbit(x);
		}
		return res;
	}
	void CLEAR(int x)
	{
		while (x < N)
		{
			tr[x] = 0;
			x += lowbit(x);
		}
	}
}tr;

int f[N];
int n;
struct Node
{
	int a, b, c, d, id;
	bool operator<(const Node& g) const
	{
		return a < g.a;
	}
}p[N];
vector<int> b;

bool cmp1(const Node& x, const Node& y)
{
	return x.d < y.d;
}

bool cmp2(const Node& x, const Node& y)
{
	return x.b < y.b;
}

void cdq(int l, int r)
{
	if (l > r) return;
	if (l == r)
	{
		f[p[l].id] = max(f[p[l].id], 1);
		return;
	}
	sort(p + l, p + r + 1);
	int mid = l + r >> 1;
	cdq(l, mid);
	sort(p + l, p + mid + 1, cmp1);
	sort(p + mid + 1, p + r + 1, cmp2);
	int i = l, j = mid + 1;
	while (j <= r)
	{
		while (i <= mid && p[i].d <= p[j].b)
		{
			tr.ins(p[i].c, f[p[i].id]);
			i++;
		}
		f[p[j].id] = max(f[p[j].id], tr.query(p[j].d) + 1);
		j++;
	}
	for (int i = l; i <= mid; i++)
	{
		tr.CLEAR(p[i].c);
	}
	cdq(mid + 1, r);
}

int main()
{
	//freopen("D:\\P3364_1.in", "r", stdin);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d%d%d%d", &p[i].a, &p[i].b, &p[i].c, &p[i].d);
		p[i].id = i;
		b.emplace_back(p[i].a);
		b.emplace_back(p[i].b);
		b.emplace_back(p[i].c);
		b.emplace_back(p[i].d);
	}
	sort(b.begin(), b.end());
	b.erase(unique(b.begin(), b.end()), b.end());
	for (int i = 1; i <= n; i++)
	{
		p[i].a = lower_bound(b.begin(), b.end(), p[i].a) - b.begin() + 1;
		p[i].b = lower_bound(b.begin(), b.end(), p[i].b) - b.begin() + 1;
		p[i].c = lower_bound(b.begin(), b.end(), p[i].c) - b.begin() + 1;
		p[i].d = lower_bound(b.begin(), b.end(), p[i].d) - b.begin() + 1;
	}
	cdq(1, n);
	int ans = 0;
	for (int i = 1; i <= n; i++) ans = max(ans, f[i]), assert(f[i] >= 1);
	printf("%d\n", ans);
	return 0;
}
posted @   HappyBobb  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示