1 条题解
-
0
自动搬运
来自洛谷,原作者为

Deu5ExMach1na
""搬运于
2025-08-24 21:55:04,当前版本为作者最后更新于2021-11-26 11:36:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
关于此题的一个新的方法:
此题其实不需要其他题解的 数组来记录什么的,整体代码长度也比较短。
关键部分的代码:
for (int i = 1; i <= n; i++) { int val = ask(num[i]) - ask(num[i] - 1); add(num[i], ask(num[i] - 1)); if (val) add(num[i], -val + 1); else add(num[i], 1); }解释如下:
储存的是原来序列的数,
, 对应的是树状数组的基操,
对于如何建立树状数组,我们可以这样来考虑:
建立数组 保存当前以 结尾的上升子序列的集合的元素个数。
如何维护 ?:
1.遍历 。
2.如果当前的数对应的集合为空,则要将 加一,让它变成 只有一个 元素,方便后续转移。
3.遍历到 时,我们将它加上 到 的和,这应该是比较好理解的, 但是若 本身有值,我们会发现出现了重复,此时把 对应集合的元素全重新计算了一遍,所以要减去 原本的值。
4.注意 没有被重复计算,所以还要 。
所以答案就是:
cout << ask(m) - m;因为 不算做上升序列。
CODE:
#include <bits/stdc++。h> #define int long long #define mod 1000000000 + 7 #define N 100007 using namespace std; int n, m; int num[N], c[N], ls[N]; void add(int x, int v) { for (; x <= m; x += x & -x) { c[x] += v; c[x] %= mod; } } int ask(int x) { int ret = 0; for (; x; x -= x & -x) { ret += c[x]; ret %= mod; } return ret; } signed main() { ios::sync_with_stdio(false); cin >> n; for (int i = 1; i <= n; i++) { cin >> num[i]; ls[i] = num[i]; } sort(ls + 1, ls + n + 1); m = unique(ls + 1, ls + n + 1) - (ls + 1); for (int i = 1; i <= n; i++) num[i] = lower_bound(ls + 1, ls + 1 + m, num[i]) - ls; for (int i = 1; i <= n; i++) { int val = ask(num[i]) - ask(num[i] - 1); add(num[i], ask(num[i] - 1)); if (val) add(num[i], -val + 1); else add(num[i], 1); } cout << ask(m) - m; return 0; }
- 1
信息
- ID
- 2924
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者