[lnsyoj2612/luoguP2766] 最长不下降子序列问题

题意

给定正整数序列 \(x_1 \ldots, x_n\),求

  1. 最长不下降子序列的长度 \(s\)
  2. 如果每个元素只允许使用一次,从给定的序列中最多可取出多少个长度为 \(s\) 的不下降子序列。
  3. 如果允许在取出的序列中多次使用 \(x_1\)\(x_n\)(其他元素仍然只允许使用一次),则从给定序列中最多可取出多少个不同的长度为 \(s\) 的不下降子序列。

sol

\(1\) 问是 LIS 板子题,记最终的结果为 \(mxn\)
\(2\) 问中,如果将序列中的元素作为点,将可以 \(dp\) 数组的转移作为边,就可以建出一个图。问题等价于求这个图中,只能覆盖每个点 \(1\) 次,给定所有源点(满足 \(dp_s=1\) 的所有点 \(s\))和汇点(满足 \(dp_t=mxn\) 的所有点 \(t\)),最多能覆盖多少个长度为 \(s-1\) 的路径。
由于容量的限制在于点而非边,这里可以使用拆点的技巧,即将一个点在网络中拆为两个点,在两点之间建一条容量为原来的点容量的弧。在这个网络上求网络流即可。
需要注意的是,由于可能存在多个起点和终点,因此需要建立超级源点和超级汇点。并向每一个可行的源汇点建弧,容量均为 \(1\)
\(3\) 问和第 \(2\) 问等价,但是由于点 \(1\) 和点 \(n\) 无容量限制,因此需要对与超级源汇点及点内部的容量进行调整。
注意特判 \(n=1\)

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>using namespace std;const int K = 505, N = K * 2, M = N * N, INF = 0x3f3f3f3f;int f[K];
int nn;
int a[K];
int mxn;
int h[N], e[M], cap[M], ne[M], idx;
int d[N], cur[N];
int n, S, T;int dp(){for (int i = 1; i <= nn; i ++ ) {f[i] = 1;for (int j = 1; j < i; j ++ )if (a[j] <= a[i])f[i] = max(f[i], f[j] + 1);}int res = 0;for (int i = 1; i <= nn; i ++ ) res = max(res, f[i]);return res;
}bool bfs() {memset(d, -1, sizeof d);queue<int> q;d[S] = 0, cur[S] = h[S], q.push(S);while (!q.empty()) {int t = q.front(); q.pop();for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (d[j] == -1 && cap[i]) {d[j] = d[t] + 1;cur[j] = h[j];if (j == T) return true;q.push(j);}}}return false;
}int find(int u, int limit){if (u == T) return limit;int flow = 0;for (int i = cur[u]; ~i && flow < limit; i = ne[i]){int j = e[i];cur[u] = i;if (d[j] == d[u] + 1 && cap[i]) {int t = find(j, min(cap[i], limit - flow));if (!t) d[j] = -1;cap[i] -= t, cap[i ^ 1] += t, flow += t;}}return flow;
}int dinic(){int r = 0, flow;while (bfs()) while (flow = find(S, INF)) r += flow;return r;
}void add(int a, int b, int c){e[idx] = b, cap[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;e[idx] = a, cap[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}void build() {memset(h, -1, sizeof h);n = nn * 2 + 2; S = n - 1, T = n;for (int i = 1; i <= nn; i ++ ) add(i * 2 - 1, i * 2, 1);for (int i = 1; i <= nn; i ++ ) if (f[i] == 1) add(S, i * 2 - 1, 1);for (int i = 1; i <= nn; i ++ ) if (f[i] == mxn) add(i * 2, T, 1);for (int i = 1; i < nn; i ++ )for (int j = i + 1; j <= nn; j ++ )if (a[i] <= a[j] && f[i] + 1 == f[j]) add(i * 2, j * 2 - 1, INF);
}void rebuild(){memset(h, -1, sizeof h);idx = 0;n = nn * 2 + 2; S = n - 1, T = n;add(1, 2, INF), add(nn * 2 - 1, nn * 2, INF);for (int i = 2; i < nn; i ++ ) add(i * 2 - 1, i * 2, 1);for (int i = 1; i <= nn; i ++ ) if (f[i] == 1) {if (i == 1) add(S, i * 2 - 1, INF);else add(S, i * 2 - 1, 1);}for (int i = 1; i <= nn; i ++ ) if (f[i] == mxn) {if (i == nn) add(i * 2, T, INF);else add(i * 2, T, 1);}for (int i = 1; i < nn; i ++ )for (int j = i + 1; j <= nn; j ++ )if (a[i] <= a[j] && f[i] + 1 == f[j]) add(i * 2, j * 2 - 1, INF);
}int main(){scanf("%d", &nn);for (int i = 1; i <= nn; i ++ ) scanf("%d", &a[i]);mxn = dp();printf("%d\n", mxn);build();printf("%d\n", dinic());if (nn == 1) return puts("1"), 0;rebuild();printf("%d\n", dinic());
}

蒟蒻犯的若至错误

  • 变量名混淆

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/874749.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

autocad Ribbon创建的一种新思路

之前开发的功能相对简单, 一个RibbonTab就把相关的功能展示出来了。 目前着手准备开发的功能, 需要多个RibbonTab, 且不想显示AutoCAD或Civil 3D自身的RibbonTab, 曾经想模拟3d3s的样子来切换RibbonTab, 但发现3d3s是将AutoCAD原生的Cuix和自己的RibbonTab结合到一起, 对…

Solon Cloud Gateway 开发:导引

Solon Cloud Gateway 是 Solon Cloud 体系提供的分布式网关实现(轻量级实现)。Solon Cloud Gateway 是 Solon Cloud 体系提供的分布式网关实现(轻量级实现)。 分布式网关的特点(相对于本地网关):提供服务路由能力 提供各种拦截支持1、分布式网关推荐 建议使用专业的分布…

Mac安装Prometheus + Grafana

一、安装Prometheus 1、下载安装 brew install prometheus2、安装路径 /opt/homebrew/Cellar/prometheus/3.1.0 3、修改配置文件 默认配置文件路径:/opt/homebrew/etc/prometheus.yml global:scrape_interval: 15sscrape_configs:- job_name: "prometheus"static_co…

Python基础6——装饰器(续) 递归 模块

1.函数1.1 参数当默认参数的值为可变类型时慎用# 不推荐使用以下代码 def func(data, value=[]):pass可以将默认参数的值改为None# 推荐使用以下代码 def func(data, value=None):if not value:value = []案例def func(data, value=[]):value.append(data)return valuev1 = fun…

C# Winform 在 Pancel 上绘制矩形

在C#的WinForms应用程序中,Panel控件本身不直接支持绘图功能,因为它不是一个绘图控件。不过,你可以通过在Panel上覆盖(override)OnPaint方法或者使用Graphics对象来在Panel上绘制图形。下面是如何实现这两种方法的示例: 方法1:覆盖OnPaint方法 可以通过重写Panel的OnPai…

SpringBoot使用SSE流,打tar包发版后出现问题

SpringBoot使用SSE流,打tar包发版后出现问题 以下纯个人实践,如有问题,还望指正~ 出现的问题 出现原因:本地调试SSE推送数据没有问题,但是通过打包为tar包发版之后,出现了以下报错: 主要问题就是: java.lang.IllegalArgumentException: Async support must be enabled …

【每日一题】20250124

读书就是这样好,无论心不在焉,板着长脸,只要考试及格,就是一个及格的人。【每日一题】 1.(20分) \(\hspace{0.6cm}\)如图所示,质量 \(M=2 \; \mathrm{kg}\) 的滑块套在光滑的水平轨道上,质量 \(m=1 \; \mathrm{kg}\) 的小球通过长 \(L=0.5 \; \mathrm{m}\) 的轻质细杆与…

Golang sync.pool源码解析

sync.Pool 是 Go 中用于对象复用的工具,可减少频繁创建和销毁对象的开销,从而优化内存使用和降低 GC 压力。本文通过分析其用法、真实案例及源码结构,详细解读了 sync.Pool 的读写流程及其背后的高效设计思想,为性能优化提供了实用参考。Golang sync.pool源码解析 - sync.p…

从靶场到实战:双一流高校多个高危漏洞

本文结合其它用户案例分析讲解挖掘某双一流站点的过程,包含日志泄露漏洞深入利用失败,到不弱的弱口令字典进入后台,再到最后偶遇一个貌似只在靶场遇到过的高危漏洞。本文结合其它用户案例分析讲解挖掘某双一流站点的过程,包含日志泄露漏洞深入利用失败,到不弱的弱口令字典…

Nginx 架构和安装

1.1 Nginx 概述 1.1.1 Nginx 介绍 Nginx:engine X ,2002年开发,分为社区版和商业版(nginx plus ) 2019年3月11日 F5 Networks 6.7亿美元的价格收购 Nginx是免费的、开源的、高性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器 解决C10K问题(10K Connect…

Linux命令大全-快速查询手册

访问地址: 线上访问:https://git.io/linux 开源社区:https://github.com/jaywcjlove/linux-command 简要介绍: Linux 命令大全搜索工具,内容包含 Linux 命令手册、详解、学习、搜集,中文解释,支持背景切换。主要功能: 当前仓库搜集了 580 多个 Linux 命令,是一个非盈利…

IPTVnator - 最方便的开源 IPTV 播放器

IPTVnator 是一款视频播放器应用程序,提供对 IPTV 播放列表播放(m3u、m3u8)的支持。该应用程序允许用户使用远程 URL 或从本地文件系统上传文件来导入播放列表。此外,它还支持 XMLTV 格式的 EPG 信息,可以通过 URL 提供。该应用程序是一个使用 Electron(目前正在迁移到 T…