Educational Codeforces Round 160 (Rated for Div. 2) D. Array Collapse(笛卡尔树+DP)

原题链接:D. Array Collapse


题目大意:


给你一个长度为 n n n 的排列 p p p ,排列的定义为 [ 1 , 2 , 3 , . . , n ] [1,2,3,..,n] [1,2,3,..,n] 中每个数都出现 恰好 一次。

你可以做 任意多次 这样的操作:

选出一个任意长度的子数组(数组中连续的一段),保留其最小的元素,并将其他元素从数组中删去。

现在询问你,按上面的方法操作之后,最终可以获得多少个互不相同的数组,答案对 998 998 998 244 244 244 353 353 353 取模后输出。

解题思路:


我们可以发现一个事实:

因为每次都是保留一个最小元素,假设我们想要保留某一个元素在最终数组里,那么我们只能删除它两边比它大的元素。

假设数组为: [ 4 , 3 , 5 , 2 , 1 , 8 , 6 , 7 ] [4,3,5,2,1,8,6,7] [4,3,5,2,1,8,6,7]

3 3 3 只能删除 [ 1 , 3 ] [1,3] [1,3] 区间的元素, 2 2 2 只能删除 [ 1 , 4 ] [1,4] [1,4] 区间的元素,而最小值 1 1 1 可以把区间 [ 1 , 8 ] [1,8] [1,8] 的元素全都删完,这里的删完是指的是除了自己以外的元素。

我们发现,每个点都管辖着一个区间,我们可以联想到 笛卡尔树 。

比如我们按照下标满足二叉搜索树,权值满足小根堆的方式按照上面的数组,所构建出来的笛卡尔树就是:

在这里插入图片描述
一个节点的子树就是他能管辖到的位置。

这样,我们就能对每个节点管辖到的左右子树进行分类讨论了。

  • 对管辖了 [ 1 , n ] [1,n] [1,n] 的根结点 1 1 1 无论如何也不能删去,没有贡献。
  • 一个节点 u u u 而言,如果我们要保留它,显然它的左右子树的方案是独立的,因此保留它的方案数有 a n s l × a n s r ansl \times ansr ansl×ansr 种。
  • 假设不保留它,而且它管辖了 [ 1 , x ] [1,x] [1,x] 的一段区间,说明它是其左边的最小值,比如 3 3 3 。我们左边没有比我们更小的数来删掉节点 u u u 了,因此我们只能被右边比我们小的 2 2 2 删去,右子树会被随之吞并,而左子树是独立的,所以方案数有 a n s l ansl ansl 种。
  • 假设不保留它,而且它管辖了 [ x , n ] [x,n] [x,n] 的一段区间,说明它是其右边的最小值,比如 6 6 6 。我们右边没有比我们更小的数来删掉节点 u u u 了,因此我们只能被左边比我们小 1 1 1 的删去,左子树会被随之吞并,而右子树是独立的,所以方案数有 a n s r ansr ansr 种。
  • 假设不保留它,而且它管辖了 [ x , y ] [x,y] [x,y] 的一段区间,说明它左右都有比他小的值 。我们既可以被左节点删除,又可以被右节点删除,所以方案数有 a n s l + a n s r − 1 ansl+ansr-1 ansl+ansr1 种。(首先左右子树是独立的,我们点 u u u 被左边删了,而右子树有一个全删完的方案,此时我们计算了一个删空点 u u u 整个子树的方案。而我们被右边删了,左子树有一个全删完的方案,此时我们又计算了一次删空点 u u u 的方案,点 u u u 的子树空被计算了两次,所以要减去 1 1 1

我们只需要从 1 1 1 开始,然后跑递归处理每个点作为子树的方案值,回溯过程中 D P DP DP 即可。

时间复杂度: O ( n ) O(n) O(n)

AC代码:

#include <bits/stdc++.h>
using namespace std;

using PII = pair<int, int>;
using i64 = long long;

template<class Ty>
struct CartesianTree {
    vector<int> stk;
    vector<int> L, R;
    CartesianTree() {}
    tuple<int, vector<int>, vector<int>> work(const vector<Ty>& A) {
        L.assign(A.size(), 0), R.assign(A.size(), 0);
        int n = A.size() - 1;
        for (int i = 1; i <= n; ++i) {
            int lst = 0;
            while (stk.size() && A[stk.back()] > A[i]) {
                lst = stk.back();
                stk.pop_back();
            }
            if (stk.size()) {
                R[stk.back()] = i;
            }
            if (lst) {
                L[i] = lst;
            }
            stk.emplace_back(i);
        }
        return {stk[0], L, R};
    }
};

const int mod = 998244353;

void solve() {
    int n;
    cin >> n;

    vector<int> arr(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> arr[i];
    }

    CartesianTree<int> T;
    auto [root, L, R] = T.work(arr);

    auto DFS = [&](auto self, int u, int l, int r) -> i64 {
        i64 ansl = 1, ansr = 1;
        if (L[u]) ansl = self(self, L[u], l, u - 1);//有左子树就去左子树
        if (R[u]) ansr = self(self, R[u], u + 1, r);//有右子树就去右子树

        i64 ans = ansl * ansr % mod;//保留根的答案
        //删除根的答案
        if (l == 1 && r == n);//跳过根节点
        else if (l == 1) {
	        //只能被右边删
            ans += ansl;
        } else if (r == n) {
            //只能被左边删
            ans += ansr;
        } else {
        	//左右都能删
            ans += ansl;
            ans += ansr;
            ans -= 1;
        }
        return (ans + mod) % mod;
    };

    cout << DFS(DFS, root, 1, n) << '\n';
}

signed main() {

    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    int t = 1; cin >> t;
    while (t--) solve();

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

8万就能买混动!秦PLUS、启源A05、帝豪L Hi-P谁值得买?

文 | AUTO芯球 作者 | 雷歌 你可以不买比亚迪&#xff0c;但一定要感谢比亚迪。 比亚迪凭着一己之力&#xff0c;将整个混动汽车的价格降到了7万元时代。 秦PLUS价格自9.98万直降2万来到7.98万后&#xff0c;它的直接竞争对手们开始降价&#xff0c;长安启源A05混动降至7.8…

Linux提权—服务漏洞,以MySQL-UDF提权为例

UDF(user defined function&#xff0c;用户自定义函数) 利用条件&#xff1a; 有对MySQL数据库进行创建&#xff0c;插入&#xff0c;删除的权限 secure_file_priv为空 利用过程 secure_file_priv的值为空或者是我们恰巧需要用到的目录&#xff0c;如下&#xff1a; 提权成…

数学建模论文、代码百度网盘链接

1.[2018中国大数据年终总决赛冠军] 金融市场板块划分与轮动规律挖掘与可视化问题 2.[2019第九届MathorCup数模二等奖] 数据驱动的城市轨道交通网络优化策略 3.[2019电工杯一等奖] 露天停车场停车位的优化设计 4.[2019数学中国网络数模一等奖] 基于机器学习的保险业数字化变革…

C#通过泛型方法的重载分别调用主窗体和提示窗体

目录 一、涉及到的知识点 1.泛型方法的重载 2.使用泛型更好地实现通用化 二、示例&#xff1a;泛型方法及其重载 1.源码 2. 生成效果 实际开发项目时&#xff0c;有时会因为调用窗体或提示窗体过多&#xff0c;而难于管理&#xff0c;这时&#xff0c;可以通过泛型方法的…

关于 REST API,你了解多少?

什么是 REST API REST 是 REpresentational State Transfer 的缩写&#xff0c;是分布式超媒体系统的架构风格。Roy Fielding 于 2000 年在他的著名论文中首次提出了这一点。从那时起&#xff0c;它已成为构建基于 Web 的 API&#xff08;应用程序编程接口&#xff09;的最广泛…

保障工作效率!实时监管员工工作微信

随着移动办公的普及&#xff0c;员工使用微信进行工作沟通已成为常态。为了实时监管员工工作微信&#xff0c;企业可以通过个微管理系统来提高效率并确保合规&#xff1a; 给员工分配微信子账号 企业管理者可以直接在系统上给员工分配子账号&#xff0c;并轻松查看子账号的工…

leetcode hot100 买卖股票的最佳时机二

注意&#xff0c;本题是针对股票可以进行多次交易&#xff0c;但是下次买入的时候必须保证上次买入的已经卖出才可以。 动态规划可以解决整个股票买卖系列问题。 dp数组含义&#xff1a; dp[i][0]表示第i天不持有股票的最大现金 dp[i][1]表示第i天持有股票的最大现金 递归公…

ElasticSearch之bool多条件查询

写在前面 在实际的业务场景中&#xff0c;不可能只是简单的单值查询 &#xff0c;更多的是n个条件的综合查询&#xff0c;就像下面的搜索&#xff1a; 针对这种场景我们就需要依赖于bool查询了&#xff0c;本文就一起来看下这部分的内容。 1&#xff1a;bool查询介绍 bool查…

在github的README.md中插入视频;在github的README.md中添加gif演示动画

最近需要再github中上传项目的源代码&#xff0c;应导师的要求&#xff0c;需要再README中加入对实验视频的展示&#xff0c;但是github的README.md其实就是一个markdown文件&#xff0c;据我的理解这个文件里应该无法直接插入视频吧&#xff1f;&#xff08;如果后续有办法直接…

python中的类与对象(2)

目录 一. 类的基本语法 二. 类属性的应用场景 三. 类与类之间的依赖关系 &#xff08;1&#xff09;依赖关系 &#xff08;2&#xff09;关联关系 &#xff08;3&#xff09;组合关系 四. 类的继承 一. 类的基本语法 先看一段最简单的代码&#xff1a; class Dog():d_…

Python Web开发记录 Day3:BootStrap

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 三、BootStrap1、BootStrap-初体验2、BootStrap…

Inno setup 打包jar包+前端dist+mysql+navicat等应用文件操作

目录 一、 使用exe4j将后端jar包打包成exe应用文件 1.创建一个新的工程 2.选择一个你想要存放的路径 3.进入配置界面 4.选择jar转换exe模式 5.自定义名字和选择输出路径 6.配置初始化 7.配置java环境 8.测试运行结果 二、Inno 打包应用文件exe 1.新建一个工程文件 2…

前端取图片相同颜色作为遮罩或者背景

需求 遮罩层取图片相同/相似的颜色作为遮罩 效果 做法 npm库 grade.js 所提供图像中前 2 个主色生成的互补渐变https://github.com/benhowdle89/grade COLOR THIEF 只需使用Javascript即可从图像中获取调色板。 https://github.com/lokesh/color-thief https://lokeshd…

向导式堆栈管理器Dockge

经过申诉&#xff0c;目前博客的几个域名都恢复了&#xff0c;时间也延长到了 2033 年&#xff0c;后面还会不会出问题&#xff0c;老苏就不知道了 什么是 Dockge ? Dockge 是一款时髦的、易于使用的、响应式的、自托管的 docker-compose.yaml 向导式堆栈管理器&#xff0c;可…

python使用winio控制x86工控机的gpio

视频讲解 https://www.bilibili.com/video/BV1Nu4m1w7iv/?vd_source5ba34935b7845cd15c65ef62c64ba82f pywinio库 https://pypi.org/project/pywinio/ 安装库 pip install pywinio寄存器地址 测试代码 import pywinio winio get_winio() # 设置排针2输出1,0x40是bit6置…

SSMBUG之 url +

1. Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured. 经查, 书写一切正常. 注意到此时yml文件的图标是一个红色的Y而不是绿色的spring , 推测没有正确加载. 重新创建项目, 所有东西拷贝一份便恢复正常…

04|MySQL事务及ACID

1 事务 事务是一组操作要么全部成功&#xff0c;要么全部失败&#xff0c;目的是为了保证数据最终的一致性。 2 事务的ACID属性 2.1 原子性(Atomicity) 当前事务的操作要么同时成功&#xff0c;要么同时失败。原子性由 undo log日志来实现。 2.2 一致性(Consistent) 使用…

爬虫入门四(抽屉半自动点赞、xpath使用、动作链、打码平台、scrapy框架介绍与安装及创建项目)

文章目录 一、抽屉半自动点赞二、xpath的使用三、动作链四、打码平台介绍超级鹰打码基本测试 五、自动登录超级鹰六、scrapy框架介绍安装创建爬虫项目 一、抽屉半自动点赞 登录抽屉账号保存cookiesimport timeimport jsonfrom selenium import webdriverfrom selenium.webdrive…

javascript给对象添加迭代器

迭代器是啥就自行百度了 为啥for…of可以遍历数组&#xff0c;为啥不能遍历对象&#xff0c;就是for…of会调用迭代器&#xff0c;而数组是内置了迭代器了&#xff0c;而对象没有内置&#xff0c;所以直接使用for…of遍历对象会报错&#xff0c;因此只用在对象的原型上面自定义…

复旦EMBA徐能:攻克新能源+关键技术,十年如一日拓荒前行

乘着“双碳”战略的东风&#xff0c;我国新能源产业迎来了重大发展机遇。在低碳绿色发展日渐成为全球共识的背景下&#xff0c;新能源产业正在发生什么变化&#xff0c;未来的发展将呈现什么格局&#xff1f;本期《同学同行》让我们一起走进复旦大学EMBA 2022级2班同学徐能和他…