跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

HDU 6635 Nonsense Time 题解:逆向思维求解动态 LIS

HDU 6635 Nonsense Time 要求在线查询元素逐个激活后的最长上升子序列长度。常规正向动态维护困难,采用逆向思维,从所有元素激活状态开始逐步移除。基于数据随机性假设,平均时间复杂度可优化至 n*sqrt(n)*log(n)。核心逻辑是倒序遍历时检查被移除元素是否属于当前 LIS,若不属则长度不变,若属则需重新计算。实现采用贪心策略配合二分查找优化 LIS 更新过程。

女王发布于 2019/8/7更新于 2026/9/854 浏览
HDU 6635 Nonsense Time 题解:逆向思维求解动态 LIS

题目描述

You are given a permutation p1, p2, ..., pn of size n. Initially, all elements in p are frozen. There will be n stages that these elements will become available one by one. On stage i, the element p[ki] will become available.

For each i, find the longest increasing subsequence among available elements after the first i stages.

输入输出

Input

The first line of the input contains an integer T (1 ≤ T ≤ 3), denoting the number of test cases.

In each test case, there is one integer n (1 ≤ n ≤ 50000) in the first line, denoting the size of permutation.

In the second line, there are n distinct integers p1, p2, ..., pn (1 ≤ pi ≤ n), denoting the permutation.

In the third line, there are n distinct integers k1, k2, ..., kn (1 ≤ ki ≤ n), describing each stage.

It is guaranteed that p1, p2, ..., pn and k1, k2, ..., kn are generated randomly.

Output

For each test case, print a single line containing n integers, where the i-th integer denotes the length of the longest increasing subsequence among available elements after the first i stages.

解题思路

题目要求在元素逐个激活的过程中,每次查询当前可用元素的最长上升子序列(LIS)长度。正向动态维护较为困难,考虑采用逆向思维。

  1. 逆向处理:从所有元素都可用开始,逐步移除元素。倒序处理时,如果移除的元素不在当前的 LIS 中,则 LIS 长度不变;如果移除的元素在 LIS 中,则需要重新计算 LIS。
  2. 复杂度分析:最坏时间复杂度为 O(n^2 * log n),但由于数据是随机生成的,平均复杂度可优化至 O(n * sqrt(n) * log n)。
  3. 实现细节:使用贪心策略配合二分查找(lower_bound)来维护 LIS。记录每个数在 LIS 中的位置,以便判断被移除的数是否关键。

参考代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;
const int MAX = 1e6 + 10;
int a[MAX], b[MAX], c[MAX], pos[MAX], ans[MAX], d[MAX];
int cnt, w, sum, n;

void solve() {
    cnt = sum = 0;
    for (int i = 0; i <= n; i++) pos[i] = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] == 0) continue;
        if (cnt == 0 || a[i] > ans[cnt]) {
            ans[++cnt] = a[i];
            pos[i] = cnt;
        } else {
            int index = lower_bound(ans + 1, ans + cnt + 1, a[i]) - ans;
            ans[index] = a[i];
            pos[i] = index;
        }
    }
    w = cnt;
    int maxx = 5201314;
    sum = 0;
    for (int i = n; i >= 1; i--) {
        if (!cnt) break;
        if (pos[i] == cnt && maxx > a[i]) {
            cnt--;
            c[sum++] = a[i];
            maxx = a[i];
        }
    }
    sort(c, c + sum);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
        solve();
        for (int i = n; i >= 1; i--) {
            int index = lower_bound(c, c + sum, a[b[i]]) - c;
            if (c[index] != a[b[i]]) {
                d[i] = w;
                a[b[i]] = 0;
                continue;
            } else {
                d[i] = w;
                a[b[i]] = 0;
                solve();
            }
        }
        for (int i = 1; i <= n; i++) {
            if (i == 1) printf("%d", d[i]);
            else printf(" %d", d[i]);
        }
        puts("");
    }
    return 0;
}

总结

本题通过逆向思维将动态增加问题转化为动态删除问题,利用随机数据的特性降低了期望复杂度。核心在于快速判断被移除元素对 LIS 的影响,并适时更新状态。

目录

  1. 题目描述
  2. 输入输出
  3. Input
  4. Output
  5. 解题思路
  6. 参考代码
  7. 总结

更多推荐文章

查看全部
  • Visual C++ 运行库安装与故障排查指南
  • Linux 基础使用与 Java 项目部署指南
  • 高并发、分布式场景下的 ID 生成策略
  • 前端实战:如何让用户回到上次阅读位置
  • Qwen3-Reranker-0.6B AR 导航空间语义排序效果解析
  • 10 个优质 Python 学习网站推荐
  • JWT 结构化知识体系:从原理到生产落地
  • DGX Spark 部署 vLLM + Open WebUI 运行 Qwen3-Coder-Next-FP8(CUDA 13.0 兼容版)
  • 基于 Coze 构建专属 AI 应用:从智能体开发到 Web 部署实战
  • 大语言模型 (LLM) 入门学习路线图
  • Qwen2.5-7B-Instruct 大模型 vLLM 推理加速与前端调用
  • IDEA 中 AI 编程插件实测:Copilot、TRAE 与灵码深度对比
  • C 语言指针与数组的深度关联及实战应用
  • 如何系统学习 AI Agent:从理论到实践
  • 前端部署:从开发到生产的全流程指南
  • Spring 排序机制:接口与注解的使用
  • Web APIs:元素滚动 scroll 系列属性详解(位置与尺寸)
  • vLLM + Open-WebUI 部署通义千问 2.5-7B 完整教程
  • Redis 基础与五大核心数据结构
  • AI 如何重构智能家居:从指令执行到主动理解

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online