算法
(树状数组优化dp+容斥) $\mathcal{O}(n\log n)$
先做一遍离散化
记 dp[i]
表示以 $a_i$ 结尾的上升子序列的个数
转移方程:
$$ dp[i] = \sum_{j < i, \, a_j < a_i} dp[j] $$
然后用树状数组加速一下即可
但这样还是不对,因为这里要求的是本质不同的上升子序列个数
我们可以考虑维护一个数组 last[x]
,用来记录上一个 $x$ 对答案的贡献,然后简单容斥一下即可
注意,最后还需要对答案容斥掉长度为 $1$ 的贡献
C++ 代码
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
// Coodinate Compression
template<typename T=int>
struct CC {
bool initialized;
vector<T> xs;
CC(): initialized(false) {}
void add(T x) { xs.push_back(x);}
void init() {
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(),xs.end()),xs.end());
initialized = true;
}
int operator()(T x) {
if (!initialized) init();
return upper_bound(xs.begin(), xs.end(), x) - xs.begin() - 1;
}
T operator[](int i) {
if (!initialized) init();
return xs[i];
}
int size() {
if (!initialized) init();
return xs.size();
}
};
//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
ll x;
mint(ll x=0):x((x%mod+mod)%mod) {}
mint operator-() const {
return mint(-x);
}
mint& operator+=(const mint a) {
if ((x += a.x) >= mod) x -= mod;
return *this;
}
mint& operator-=(const mint a) {
if ((x += mod-a.x) >= mod) x -= mod;
return *this;
}
mint& operator*=(const mint a) {
(x *= a.x) %= mod;
return *this;
}
mint operator+(const mint a) const {
return mint(*this) += a;
}
mint operator-(const mint a) const {
return mint(*this) -= a;
}
mint operator*(const mint a) const {
return mint(*this) *= a;
}
mint pow(ll t) const {
if (!t) return 1;
mint a = pow(t>>1);
a *= a;
if (t&1) a *= *this;
return a;
}
// for prime mod
mint inv() const {
return pow(mod-2);
}
mint& operator/=(const mint a) {
return *this *= a.inv();
}
mint operator/(const mint a) const {
return mint(*this) /= a;
}
};
istream& operator>>(istream& is, mint& a) {
return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
return os << a.x;
}
template<typename T>
struct BIT {
int n;
vector<T> d;
BIT(int n=0):n(n),d(n+1) {}
void add(int i, T x=1) {
for (i++; i <= n; i += i&-i) {
d[i] += x;
}
}
T sum(int i) {
T x = 0;
for (i++; i; i -= i&-i) {
x += d[i];
}
return x;
}
T sum(int l, int r) {
return sum(r-1) - sum(l-1);
}
};
int main() {
cin.tie(nullptr) -> sync_with_stdio(false);
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
int m;
{
CC cc;
rep(i, n) cc.add(a[i]);
rep(i, n) a[i] = cc(a[i]);
m = cc.size();
}
mint ans;
BIT<mint> t(m);
vector<mint> last(m);
rep(i, n) {
mint x = t.sum(a[i]-1)+1;
ans += x-last[a[i]];
t.add(a[i], x-last[a[i]]);
last[a[i]] = x;
}
ans -= m;
cout << ans << '\n';
return 0;
}