P3970 [TJOI2014]上升子序列
题目描述
给定一个只包含整数的序列(序列元素的绝对值大小不超过10^9),你需要计算上升子序列的个数,满足如下条件的称之为一个上升子序列:
是原序列的一个子序列
长度至少为2
所有元素都严格递增
如果两个上升子序列相同,那么只需要计算一次。例如:序列{1,2,3,3}有4个上升子序列,分别为{1,2}{1,3},{1,2,3},{2,3}
输入格式
输入的第一行是一个整数n,表示序列长度。接下来一行是n个整数,表示序列。
输出格式
输出仅包含一行,即原序列有多少个上升子序列。由于答案可能非常大,你只需要输出答案模10^9+7的余数。
输入输出样例
输入 #1复制
4
1 2 3 3
输出 #1复制
4
说明/提示
数据范围
对于 30% 的数据,N ≤ 5000
对于 100% 的数据,N ≤ 10^5
题解
相同的数,贪心的考虑最后一个位置的该数的贡献,树状数组维护一下和就好了
/*
hello world!
Just do it!
start time:2022-04-20 21:18:10.686777
*/
// #pragma GCC optimize (2)
// #pragma G++ optimize (2)
#include <bits/stdc++.h>
#define zero(x) memset(x, 0, sizeof(x));
#define one(x) memset(x, -1, sizeof(x));
#define m_INF(x) memset(x, 0x3f, sizeof(x));
#define m_inf(x) memset(x, 0x3f, sizeof(x));
#define m_f_INF(x) memset(x, -0x3f, sizeof(x));
#define m_f_inf(x) memset(x, -0x3f, sizeof(x));
#define all(x) x.begin(), x.end()
#define endl "\n"
#define fi first
#define se second
#define lbt(x) ((x)&(-x))
#define pb push_back
struct cmpl{ template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return b1 < a1; } };
struct cmpg{ template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return a1 < b1; } };
#define p_ql(x) priority_queue<x, vector<x>, cmpl>
#define p_qlp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpl>
#define p_qg(x) priority_queue<x, vector<x>, cmpg>
#define p_qgp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpg>
template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
#define fo(i,from,to) for(int i=(from),ooo=(from)<(to)?1:-1,oooo=(to)+ooo;i!=oooo;i+=ooo)
#define fol(i,from,to) for(long long i=(from),ooo=(from)<(to)?1:-1,oooo=(to)+ooo;i!=oooo;i+=ooo)
#define foo(i,ooo) for(auto i=ooo.rbegin();i!=ooo.rend();++i)
#define foa(i,from,to) for(int i=(from),ooo=(to);i<=ooo;++i)
#define fos(i,from,to) for(int i=(from),ooo=(to);i>=ooo;--i)
using namespace std;
#ifndef LOCAL
# define dbg(...) ;
#endif
#define itn int
#define int long long
#ifdef int
#define inf (0x3f3f3f3f3f3f3f3f)
#else
#define inf (0x3f3f3f3f)
#endif
typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii;
const int dir[8][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}}, INF = 0x3f3f3f3f, f_inf = -1044266559, f_INF = -1044266559;
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 10;
const int N = 1e6 + 10;
int n, m;
void init()
{
}
int a[N], b[N], c[N], p[N];
void inc(int &x, int y)
{
x = ((x + y) % mod + mod) % mod;
}
void add(int x, int d)
{
for(; x < N; x += lbt(x)) inc(c[x], d);
}
int query(int x)
{
int res = 0;
for(; x; x -= lbt(x)) inc(res, c[x]);
return res;
}
int v[N];
void solve()
{
cin >> n;
foa(i, 1, n) {
cin >> a[i];
b[i] = a[i];
}
sort(b + 1, b + n + 1);
int len = unique(b + 1, b + n + 1) - b - 1;
foa(i, 1, n) {
a[i] = lower_bound(b + 1, b + len + 1, a[i]) - b;
p[a[i]] = i;
}
int ans = 0;
foa(i, 1, n) {
int t = query(a[i] - 1);
if(p[a[i]] == i) inc(ans, t);
add(a[i], t + 1 - v[a[i]]);
v[a[i]] = t + 1;
dbg(i, a[i], t)
}
cout << ans << endl;
dbg(a, v)
}
signed main()
{
#ifdef LOCAL
freopen("read.in", "r", stdin);
freopen("write.out", "w", stdout);
#endif
std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
init();
int t = 0, num2 = 0;
t = 1;
if (!t) cin >> t;
while (t--) {
//cout<<"Case "<<++num2<<": ";
solve();
}
return 0;
int num1 = 0;
//while (scanf("%d", &n) !=-1 && n)
while (cin >> n && n) {
//cout<<"Case "<<++num1<<": ";
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通