NC54585 小魂和他的数列

这篇具有很好参考价值的文章主要介绍了NC54585 小魂和他的数列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目链接

题目

题目描述

一天,小魂正和一个数列玩得不亦乐乎。
小魂的数列一共有n个元素,第i个数为Ai。
他发现,这个数列的一些子序列中的元素是严格递增的。
他想知道,这个数列一共有多少个长度为K的子序列是严格递增的。

请你帮帮他,答案对998244353取模。

对于100%的数据,1≤ n ≤ 500,000,2≤ K ≤ 10,1≤ Ai ≤ 109。

输入描述

第一行包含两个整数n,K,表示数列元素的个数和子序列的长度。
第二行包含n个整数,表示小魂的数列。

输出描述

一行一个整数,表示长度为K的严格递增子序列的个数对998244353取模的值。

示例1

输入

5 3
2 3 3 5 1

输出

2

说明

两个子序列分别是 2 3 3 5 1 和 2 3 3 5 1 。

题解

知识点:树状数组,枚举,线性dp。

仿照最长上升子序列的状态,设 \(f_{i,j}\) 为以第 \(i\) 个数结尾且长度为 \(j\) 的上升子序列个数,显然是 \(O(n^2k)\) 的。其中可以优化的步骤是,查找上一个比自己小的元素。对于最长上升子序列优化查找的步骤,通常有三种方法,我们依次考虑是否适合用于这道题的状态:

  1. 改变状态,设 \(f_i\) 为长度为 \(i\) 的上升子序列的最小结尾数字,其有单调递增的性质,因此每次新增数字,二分查找最后一个小于自己数字的位置即可。但是,这个显然不适合用来优化这道题的状态。
  2. 优化查找,用数据结构维护前缀权值最大值,即以数字作为下标维护每个数字结尾的最大长度。这个方法是可以考虑的,我们将维护最大长度改为各个长度的上升子序列个数即可。
  3. 排序+优化查找,将数字顺序改为从小到大输入,用数据结构维护前缀最大值,即在原本的区间上维护每个位置结尾的最大长度,输入顺序保证了每次询问的答案一定都是比自己小的数字构成的答案,都是可以接上的。这个方法同样也是可以考虑的,我们将维护最大长度改为各个长度的上升子序列个数即可。

第二种方法需要先离散化,我们这里使用的是第三种方法,先排序后优化查找,复杂度上是没有区别的。

需要注意的是,使用第三种方法从小到大枚举时,因为要求的是上升子序列,所以相等的数字不能直接更新到数据结构中,需要等到所有相等的数字都查询完,才能一并更新。第二种方法由于直接维护权值关系,大小可以直接确定,则没有这种情况。

时间复杂度 \(O(nk \log n)\)

空间复杂度 \(O(nk)\)文章来源地址https://www.toymoban.com/news/detail-434571.html

代码

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

const int P = 998244353;

template<class T>
class Fenwick {
    int n;
    vector<T> node;

public:
    Fenwick(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        node.assign(n + 1, T());
    }

    void update(int x, T val) { for (int i = x;i <= n;i += i & -i) node[i] += val; }

    T query(int x) {
        T ans = T();
        for (int i = x;i;i -= i & -i) ans += node[i];
        return ans;
    }
};

int k;
struct T {
    array<int, 17> f = {};
    T &operator+=(const T &x) {
        for (int i = 1;i <= k;i++) (f[i] += x.f[i]) %= P;
        return *this;
    }
};

pair<int, int> a[500007];
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n >> k;
    for (int i = 1;i <= n;i++) {
        int x;
        cin >> x;
        a[i] = { x,i };
    }
    sort(a + 1, a + n + 1, [&](auto a, auto b) {return a.first < b.first;});

    int ans = 0;
    Fenwick<T> fw(n);
    vector<pair<int, array<int, 17>>> v;
    for (int i = 1;i <= n;i++) {
        if (a[i].first != a[i - 1].first) {
            for (auto [id, f] : v) fw.update(id, { f });
            v.clear();
        }
        auto res = fw.query(a[i].second).f;
        for (int j = k;j >= 1;j--) res[j] = res[j - 1];
        res[1] = 1;
        (ans += res[k]) %= P;
        v.push_back({ a[i].second,res });
    }
    cout << ans << '\n';
    return 0;
}

到了这里,关于NC54585 小魂和他的数列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 看看你的对象是啥种,他的生命历程又是怎样的呢?

    看到标题满脑大大的疑问 如上图 是个什么鬼。今天我们就来介绍一下对象的类型用与区分你的对象。 基础类型与数据类型 八种 基本数据类型 : int、short、float、double、long、boolean、byte、char。 对应的 封装类 是: Integer、Short、Float、Double、Long、Boolean、Byte、Character。 从作用

    2023年04月15日
    浏览(22)
  • 对 blur 平台上面的任意地址,获取他的出价信息(附代码)

    对 blur 平台上面的任意用户地址,获取他的出价信息 代码是 Python 脚本,可用于采集用户的出价信息。 脚本定义一个 save_userinfo 函数,该函数用于将用户的出价信息写入 CSV 文件。该函数接收两个参数:文件名和文本。它将文本写入文件,并换行。 还定义了 headers 字典,该字

    2024年02月14日
    浏览(18)
  • 网络安全先驱传奇大佬自杀了,他的一生足够拍成一部电影

    据西班牙报纸 El Pais 报道,网络安全先驱 John McAfee 在西班牙的监狱中死亡,享年 75 岁。 McAfee 的律师称,John McAfee 在九个月的监禁中因绝望而自杀。目前监狱当局正在调查死因。 如果把 John McAfee 的一生拍成电影的话,估计连最牛逼的编剧都不敢这样设计。 他贩毒、酗酒、乱

    2024年02月11日
    浏览(26)
  • 前端如何利用js开启摄像头和关闭摄像头以及他的指示灯

    其实本文章主要想要讲解的就是如何关闭摄像头以及他的指示灯,因为这个事真的很让我苦恼,而开启摄像头其实并没有那么难,只需调用navigator.mediaDevices.getUserMedia方法就行,具体就不细讲了,直接上代码(HTML结构就是一个video标签和两个button按钮,所以就只上js部分了) 开启

    2024年02月13日
    浏览(31)
  • 一篇文章带你了解 什么是u(ustd)带你了解他的前世今生

    在数字货币的繁荣世界中,USDT无疑是其中一位重要的角色。它的前世今生,是一个从无到有,从小到大,经历了种种波折和争议的故事。 2014年11月下旬,一个名为Realcoin的注册地为马恩岛和香港的公司决定改变自己的名字,取名为Tether。这个决定预示着一种新的数字货币即将

    2024年01月23日
    浏览(35)
  • 数据分析师真实的工作是怎样的?看完他的一天,才明白为什么别人比你挣得多

    如果你认为数据分析师只能跑数据,那可千错万错了,数据分析师的真实工作究竟如何? 昨天就又双叒被支付宝的账单刷屏了。在这个大数据时代,通过数据,不仅可以分析消费行为,还可以分析一个人社交媒体及在互联网中的社会影响力、知名度及社会地位,而且加上实名

    2024年02月08日
    浏览(35)
  • NC200204 数位 DP

    题意 传送门 NC200204 dh的帽子 题解 可以独立考虑每一位是否合法。维护数字上下界的状态,枚举三个数字,仅对合法的状态进行转移。数位 DP 求解即可,时间复杂度 O ( l o g R ) O(logR) O ( l o g R ) 。

    2024年02月16日
    浏览(31)
  • NC19469 01串

    题目链接 题目描述 I used to believe We were burning on the edge of something beautiful Something beautiful Selling a dream Smoke and mirrors keep us waiting on a miracle On a miracle Say go through the darkest of days Heaven\\\'s a heartbreak away Never let you go Never let me down OH it\\\'s been a hell of a ride Driving the edge of a knife Never let you

    2024年02月02日
    浏览(21)
  • ArcGIS处理nc数据步骤

    使用ArcGIS读取nc文件步骤: 1.打开ArcGIS,在多维工具下选择“创建NetCDF栅格图层” 2.输入nc文件,其他参数可忽略,点击确定 3.创建好后,右键点击图层,点击属性,选择“NetCDF”,然后选择波段纬度,接着点击纬度对应的值,这里维度值对应的是时间,选择任意一个时间。

    2024年02月15日
    浏览(28)
  • Netcat安装与使用(nc)

      Netcat 是一款简单的Unix工具,使用UDP和TCP协议,被称为网络工具中的\\\"瑞士军*刀\\\"。它是一个可靠的容易被其他程序所启用的后台操作工具,同时它也被用作网络的测试工具或黑客工具。 使用它你可以轻易的建立任何连接。   在Linux中都是自带Netcat的,如果没有,可以使

    2023年04月22日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包