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)\) 的。其中可以优化的步骤是,查找上一个比自己小的元素。对于最长上升子序列优化查找的步骤,通常有三种方法,我们依次考虑是否适合用于这道题的状态:
- 改变状态,设 \(f_i\) 为长度为 \(i\) 的上升子序列的最小结尾数字,其有单调递增的性质,因此每次新增数字,二分查找最后一个小于自己数字的位置即可。但是,这个显然不适合用来优化这道题的状态。
- 优化查找,用数据结构维护前缀权值最大值,即以数字作为下标维护每个数字结尾的最大长度。这个方法是可以考虑的,我们将维护最大长度改为各个长度的上升子序列个数即可。
- 排序+优化查找,将数字顺序改为从小到大输入,用数据结构维护前缀最大值,即在原本的区间上维护每个位置结尾的最大长度,输入顺序保证了每次询问的答案一定都是比自己小的数字构成的答案,都是可以接上的。这个方法同样也是可以考虑的,我们将维护最大长度改为各个长度的上升子序列个数即可。
第二种方法需要先离散化,我们这里使用的是第三种方法,先排序后优化查找,复杂度上是没有区别的。
需要注意的是,使用第三种方法从小到大枚举时,因为要求的是上升子序列,所以相等的数字不能直接更新到数据结构中,需要等到所有相等的数字都查询完,才能一并更新。第二种方法由于直接维护权值关系,大小可以直接确定,则没有这种情况。
时间复杂度 \(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 小魂和他的数列的更多相关文章
- 陕西师范大学第七届程序设计竞赛网络同步赛 J 黑猫的小老弟【数论/法拉数列/欧拉函数】
链接:https://www.nowcoder.com/acm/contest/121/J来源:牛客网 题目描述 大家知道,黑猫有很多的迷弟迷妹,当然也有相亲相爱的基友,这其中就有一些二五仔是黑猫的小 ...
- 【BZOJ 1430】 1430: 小猴打架 (Prufer数列)
1430: 小猴打架 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 625 Solved: 452 Description 一开始森林里面有N只互不相 ...
- java小程序 示例 菲薄垃圾数列
package com.test; import java.util.Scanner; import org.junit.Test; import com.sun.xml.internal.ws.ap ...
- E - 小晴天老师系列——我有一个数列!
E - 小晴天老师系列——我有一个数列! Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/O ...
- [编程题] 小易喜欢的数列 dp
https://www.nowcoder.com/question/next?pid=6291726&qid=112729&tid=12736753 [编程题] 小易喜欢的数列 时间限 ...
- acdream 小晴天老师系列——我有一个数列! (ST算法)
小晴天老师系列——我有一个数列! Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)S ...
- 小X归来 模拟赛1 解析
Problem1 单峰 小X 归来后,首先对数列很感兴趣.他想起有1类特殊的数列叫单峰数列. 我们说一个数列 {ai} 是单峰的,当且仅当存在一个位置 k 使得 ai < ai+1(i < ...
- lly的数列询问(最小生成树 + 思维)
lly的数列询问 Description 这个问题很简单,lly lly lly给你一些提示,让你试着确定长度为n n n的数列A [1] A [2] ... A [n]的值,但是他想尽一切办法为大家 ...
- 基本排序算法的Python实现
本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...
- bzoj1005 [HNOI2008]明明的烦恼
1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3032 Solved: 1209 Description ...
随机推荐
- tag 总结
通用的: (((masterpiece))),((best quality)),ultra-detailed,extremely detailed CG unity 8k wallpaper,best ...
- 第3章---数据探索(python数据挖掘)
1.缺失值分析及箱型图 数据:catering_sale.xls(餐饮日销额数) 缺失值使用函数:describe()函数,能算出数据集的八个统计量 import pandas as pd cater ...
- ADOStoredProc动态调用存储过程
有些用ADOStoredProc进行操作时,要动态创建输入输出参数,一定要用 ADOStoredProc1.Parameters.Refresh;将参数进行刷新一下.
- MOBIUS: Towards the Next Generation of Query-Ad Matching in Baidu's Sponsored Search——百度下一代搜索广告系统
简介 传统的广告最终的呈现需要经过召回与排序两个阶段,百度的搜索架构则采用三层漏斗状,如图1所示.最上面的一层用于筛选出和用户查询最相关的一部分广告,将整个候选广告集从亿级降到千级:下面两层是排序阶段 ...
- Python项目案例开发从入门到实战 - 书籍信息
Python项目案例开发从入门到实战 - 爬虫.游戏和机器学习(微课版) 作者:郑秋生 夏敏捷 清华大学出版社 ISBN:978-7-302-45970-5
- 如何让excel不转换科学技术法
使用场景: 业务部门从系统导出数据给开发人员,打开后数字全部变为科学计数法 参考文章:https://www.zhihu.com/question/20096750
- 小笨自采集在线电脑壁纸 v2.0-支持移动端自适应,支持https
这周闲着没事,翻着网站,记得去年的发表的一篇文章小笨分享一款高清电脑壁纸API,主要是将孟坤壁纸改造支持https,还加了一个搜索功能.以前的壁纸是这样的: 但是,不支持移动端浏览,于是小笨趁着这周周 ...
- uni-app云开发入门
云函数 首先创建一个uniapp项目,创建项目时选择启用uniCloud云开发. 创建项目成功后,按照下面的步骤进行开发. 创建云函数 1.关联云服务器 2.创建云函数 一个云函数可以看成是一个后 ...
- 正则表达式(cases)
匹配不含'aaa'和'bbb'的字符串: ^(?!.*aaa)(?!.*bbb).*$ To be continue...
- requests不带参数的get请求和带get参数请求
requests库常用的方法 requests.Request(url) 构造一个请求,支持以下各种方式 requests.get() 发送get请求 requests.post() 发送post请求 ...