专栏文章
2025 超新星战队 B 队暑假集训模拟赛 day1
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioe4iyb
- 此快照首次捕获于
- 2025/12/02 17:43 3 个月前
- 此快照最后确认于
- 2025/12/02 17:43 3 个月前
A. LIS
题面
给一个数组 ,定义 的值为:
-
设当前索引为 ,答案为 。
-
对于 ,选取最小的 ,满足 。如果找不到 ,则结束程序。
-
让 ,并将答案增加 。然后跳转到步骤 2。
求
输入格式
第一行包含一个整数 ,表示 组测试数据。
对于每组测试数据:
第一行包含一个整数 。
接下来一行包含 个整数 。
输出格式
对于每组测试数据,输出一行包含一个整数,表示答案。
数据范围
对于所有数据,保证 。
思路
先固定 。套路地,设 为 ,则有 。
设 为满足 的最小的 ,若不存在这样的 ,则设 。
设 。注意到 ,,同理可得 ,……
设 。因为有 ,所以如果将 视作 的一条有向边,那么 就是一张以 为根的树。
设 为所有点 的 之和,满足 在 到 的简单路径上。容易在 时间计算出 的和,即答案。
实现
CPP#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int N = 400000 + 1;
int a[N + 1], stk[N + 1], f[N + 1];
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
a[n + 1] = 1 << 30;
f[n + 1] = 0;
int top = 1;
stk[top] = n + 1;
for (int i = n; i; --i) {
while (top && a[stk[top]] <= a[i]) {
--top;
}
f[i] = n - i + 1 + f[stk[top]];
stk[++top] = i;
}
cout << accumulate(f + 1, f + n + 1, 0ll) << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
时空复杂度:均为 。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...