P3970 [TJOI2014]上升子序列

题目描述

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;

}
posted @   1564269628  阅读(20)  评论(0编辑  收藏  举报
编辑推荐:
· 基于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最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示