题目链接

题目

题目描述

一天,小魂正和一个数列玩得不亦乐乎。

小魂的数列一共有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)\)

代码

#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 小魂和他的数列的更多相关文章

  1. 陕西师范大学第七届程序设计竞赛网络同步赛 J 黑猫的小老弟【数论/法拉数列/欧拉函数】

    链接:https://www.nowcoder.com/acm/contest/121/J来源:牛客网 题目描述 大家知道,黑猫有很多的迷弟迷妹,当然也有相亲相爱的基友,这其中就有一些二五仔是黑猫的小 ...

  2. 【BZOJ 1430】 1430: 小猴打架 (Prufer数列)

    1430: 小猴打架 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 625  Solved: 452 Description 一开始森林里面有N只互不相 ...

  3. java小程序 示例 菲薄垃圾数列

    package com.test; import java.util.Scanner; import org.junit.Test; import com.sun.xml.internal.ws.ap ...

  4. E - 小晴天老师系列——我有一个数列!

    E - 小晴天老师系列——我有一个数列! Time Limit: 20000/10000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/O ...

  5. [编程题] 小易喜欢的数列 dp

    https://www.nowcoder.com/question/next?pid=6291726&qid=112729&tid=12736753 [编程题] 小易喜欢的数列 时间限 ...

  6. acdream 小晴天老师系列——我有一个数列! (ST算法)

    小晴天老师系列——我有一个数列! Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)S ...

  7. 小X归来 模拟赛1 解析

    Problem1 单峰 小X 归来后,首先对数列很感兴趣.他想起有1类特殊的数列叫单峰数列. 我们说一个数列 {ai} 是单峰的,当且仅当存在一个位置 k 使得 ai < ai+1(i < ...

  8. lly的数列询问(最小生成树 + 思维)

    lly的数列询问 Description 这个问题很简单,lly lly lly给你一些提示,让你试着确定长度为n n n的数列A [1] A [2] ... A [n]的值,但是他想尽一切办法为大家 ...

  9. 基本排序算法的Python实现

    本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...

  10. bzoj1005 [HNOI2008]明明的烦恼

    1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3032  Solved: 1209 Description ...

随机推荐

  1. SqlServer提示对象名无效

    执行脚本 exec sp_msforeachtable "sp_changeobjectowner '?','dbo'"

  2. C++ read 读取字节数与设置不一样

    当需要读取二进制文件时,C++可以采用ofstream流,并设置模式为ios::binary,就可以通过read函数进行按照字节读取了. 需要注意的是: 如果模式未进行设置,默认将以文本方式读取,此时 ...

  3. 关于UPD章节学习的一些感想

    课程看到了UDP, 首先了解UDP的原理模型. 服务端,首先是实例QUdpSocket,也就是UDP套接字,然后,需要绑定.绑定一个任意IP地址,分为IPV4和IPV6.自行选择课程中讲解时绑定的是I ...

  4. python之pyqt5-第一个pyqt5程序-图像压缩工具(2.0版本)-小记

    (如想转载,请联系博主或贴上本博地址) 此篇为上一篇pyqt5图像压缩小工具改良版.因为比较简单,下面直接贴上代码. 效果图: # -*- coding: utf-8 -*- # Form imple ...

  5. python之自动化连连看脚本-第二关下移-小记

    (如想转载,请联系博主或贴上本博地址) 参考前一篇基础上,做出第二关下移逻辑判断,写的比较啰嗦. 下移和第一关不动基础代码是一样的.需要注意同列下移和不同列下移2种情况,同列下移需要注意相邻的2个和不 ...

  6. TP5中redirect实现重定向及带参数跳转

    1.控制器 重定向url传参 try{ $result = Db::name('wupin')->insert($ist); if($result){ $this->redirect(ur ...

  7. Winform 应用DotnetBar

    Winform 使用NotNetBar namespace WindowsFormExample { public partial class FrmMain : Office2007Form { p ...

  8. Linux shell usage()使用说明

    usage()类似于执行文件-help展示的内容,即告诉使用者有哪些参数选项可供使用. usage()格式 点击查看代码 #!/bin/bash usage() { echo "Usage: ...

  9. 利用MVC三层架构做一个案例(利用MyBatis实现增删改查)

    查询所有 利用昨天学习到的MyBatis知识,再加上servlet页面的跳转, demo1.jsp UserMapper.java(接口) servletDemo.java MyBatisDemo.j ...

  10. day06-静态资源访问&Rest风格

    SpringBoot之静态资源访问&REST风格请求 1.SpringBoot静态资源访问 1.1基本介绍 只要静态资源是放在类路径下的:/static./public./resources. ...