Luogu3845 [TJOI2007]球赛(Dilworth定理)题解

前置芝士

Dilwoth定理or你已经做了导弹拦截

什么是Dilworth定理?

对于任意有限偏序集,其最大反链中元素的数目必等于最小链划分中链的数目.

​ --百度百科

或许你可以通过这篇神的博客学习一下。

事实上,对于本题而言,所有的比分信息就是偏序集,而我们要求的就是最小链划分,即为最大反链长度,更具体的,就是最长严格下降子序列的长度

思路

首先,我们将所有信息按照y或者x排序,这样就保证了其中一维的有序,然后根据另一维求一遍最长下降子序列就可以了。

Tips

其实本题最优秀的复杂度应为nlogn,但是本题只要求n2,为了提升水平打最优解,建议用nlogn算法求最长下降子序列。本题解中也是用的这个复杂度的算法。

代码

copy
#include <cstdio> #include <algorithm> #define LL long long using namespace std; const int maxn = 2020; int n,top; LL b[maxn]; struct Gam{ LL x,y; }g[maxn]; bool cmp(Gam a, Gam b){return a.x == b.x ? a.y < b.y : a.x < b.x;} int main(){ int T; scanf("%d", &T); while(T--){ top = 0; scanf("%d", &n); for(int i = 1; i <= n; ++ i){ scanf("%lld-%lld", &g[i].x, &g[i].y); if(g[i].x > g[i].y) swap(g[i].x, g[i].y); } sort(g + 1, g + 1 + n, cmp); b[++top] = g[1].y; for(int i = 2; i <= n; ++ i){ if(g[i].y < b[top]) b[++top] = g[i].y; else{ int h = top, l = 1; while(h >= l){ int mid = (h + l) >> 1; if(b[mid] <= g[i].y) h = mid - 1; else l = mid + 1; } b[h + 1] = g[i].y; //printf("%d\n", h + 1); } } printf("%d\n", top); } return 0; }
posted @   When_C  阅读(114)  评论(1编辑  收藏  举报
编辑推荐:
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
阅读排行:
· “你见过凌晨四点的洛杉矶吗?”--《我们为什么要睡觉》
· C# 从零开始使用Layui.Wpf库开发WPF客户端
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
· 编程神器Trae:当我用上后,才知道自己的创造力被低估了多少
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起