P1233 [ICPC 2001 Taejon R] 木棍加工

题目链接:

P1233 ICPC 2001 Taejon R 木棍加工 - 洛谷

思路:求一个数列中最长严格上升子序列的最大长度

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,ans = 0;
int main()
{
    cin >> n;
    vector<pair<int,int>> arr(n);
    for(int i = 0;i <n ;i++)  cin >> arr[i].first >> arr[i].second;
    auto cmp = [](pair<int,int> a,pair<int,int> b){
        if(a.first != b.first)return a.first > b.first;
        return a.second > b.second;
    };
    sort(arr.begin(),arr.end(),cmp);
    vector<int> dp(n,1);
    for(int i = 0;i < n ;i++)
    {
        for(int j = 0;j < i;j++)
        {
            if(arr[i].second > arr[j].second) dp[i] = max(dp[i],dp[j] + 1);
        }
        ans = max(ans,dp[i]);
    }
    cout << ans;
    return 0;
}

首先将数组以第一个键进行排序 这样就保证了长度在数列是严格递减的

然后就是处理宽度的问题:

排完之后,看宽度的序列。比如样例:

复制代码
长度降序排完:(5,2) (4,9) (3,5) (2,1) (1,4)
宽度序列:      2     9     5     1     4

现在的问题:把这个序列分成尽量少的"不上升"子串。

复制代码
2, 1         ← 一条
9, 5, 4      ← 一条

两条。 所以答案是 2。

为什么不升子串的条数 = 最长上升子序列的长度

例子

复制代码
排好的序列:  3   1   4   2
位置:        0   1   2   3

问题 :把这四个数分成尽量少的几堆,每一堆从左往右不许上升(只能递减或相等)。

先算一个东西:每个位置"能被多长的上升串接上"

记号 dp[i]:

以第 i 个数结尾的、最长的上升子串,有多长。

复制代码
i=0,数 3:  前面没人,光它自己      → dp = 1
i=1,数 1:  前面只有 3,3 比 1 大,接不上 → dp = 1
i=2,数 4:  3<4 能接(1+1=2);1<4 能接(1+1=2) → dp = 2
i=3,数 2:  1<2 能接(1+1=2);3、4 都比它大 → dp = 2

数:   3   1   4   2
dp:   1   1   2   2

最大的 dp 是 2。 所以最长上升子序列长度 L = 2 (比如 3,4,或者 1,2)。

现在按 dp 的值分堆

复制代码
dp = 1 的:  3   1
dp = 2 的:      4   2

看这两堆里面:

复制代码
3 → 1     不上升 ✓
4 → 2     不上升 ✓

两堆,每堆都合法。分完了。

为什么"同一堆一定不上升"

这是整件事的关键

假设同一堆里,出现了两个数,后面的比前面的大:

复制代码
...  a  ...  b  ...      且 a < b,且 dp 相同

那 b 的 dp 怎么可能是同一个?

因为 a < b,b 就能把"以 a 结尾的那条上升串"整个接过来 ,长度是 dp[a] + 1。

这比 dp[b] 大,矛盾。

所以:同一堆里,后面的数不可能比前面大。 只能一路不增。

这就是为什么"按 dp 分堆"是合法的。

那堆数为什么正好是 L?

dp 的取值,最小是 1,最大是 L。

所以最多只有 L 堆(1、2、...、L)。

再看"为什么不能少于 L"

找一条最长的上升子序列,长度是 L。

比如 3, 4。

这两个数,能待在同一堆里吗?

不能。 因为 3 < 4,是上升的------而同一堆里不许上升。

所以这条 L 长的子序列里,每个数都必须独占一堆。

堆数 ≥ L。

两边一夹

复制代码
堆数 ≥ L     (上升子序列逼出来的)
堆数 ≤ L     (按 dp 分,最多 L 堆)
→ 堆数 = L

知道这个后 这个题就简单了

相关推荐
论文复现现场3 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi3 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
TMedical3 小时前
MedPlanning 截骨模拟矫形功能
c++·图像处理·人工智能·qt·健康医疗
qq_406981033 小时前
共享变量一 关于extern与const
开发语言·c++
秋天的怀念_David4 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院4 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng5 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
chari克里5 小时前
QT5.15.2 + msvc2022部署全流程说明(windows可联网环境)
开发语言·c++·qt
码匠许师傅6 小时前
【C++三方组件】mbedTLS:面向嵌入式的轻量 TLS
开发语言·c++