P3970 [TJOI2014]上升子序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
![](https://i-blog.csdnimg.cn/blog_migrate/735122d4fa789166681e94b73e7cdd9c.png)
#include <bits/stdc++.h>
#include <iostream>
#include<unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long LL ;
typedef unsigned long long ULL ;
typedef pair<int,int> PII ;
typedef pair<LL,int> PLI ;
const int N = 1e6+10,mod = 1e9 + 7 ;
const LL INF2 = 1e17;
map<LL,LL> ma;
int n,m;
LL a[N],b[N];
bool f[N];// 记录一个数 是否是第一次出现
LL lastans[N],tr[N];
// lastans 这个数上一次出现时对 答案的 影响
int lowbit(int x)
{
return x & -x;
}
void add(int x,LL v)
{
for(int i=x;i <=n ;i+= lowbit(i))
tr[i] = (tr[i] + v ) % mod;
}
LL query(LL x)
{
LL ans =0;
for(int i=x;i;i-= lowbit(i))
ans = (ans + tr[i]) % mod ;
return ans ;
}
inline void solve()
{
cin >> n;
for(int i= 1; i<= n; i++ ) cin >> a[i],b[i] = a[i];
sort(b + 1, b + 1 + n);
int tot = unique(b + 1, b + 1 +n ) -(b + 1 );
for(int i=1;i<= tot; i ++ ) ma[b[i]] = i;
// ma[i] i这个数在原序列的 从小到大的排序的排名
LL cnt =0;
for(int i=1;i <= n;i ++ )
{
int j= ma[a[i]];
if(!f[j]) // 当前这个数是第一次出现
{
LL x = query(j-1);// 比当前这个数 小的数的个数x
cnt = (cnt +x ) % mod;
add(j,x+ 1);// 在当前这个数的 位置 插入 x + 1
lastans[j] =x;
f[j] = 1;
continue;
}
LL x = query(j-1);
cnt = (cnt + x - lastans[j] + mod ) % mod;
//之前 cnt 已经加过了 j 这个排名 第一次 出现的影响 ,当前j 的影响 包含之前的影响要减去
add(j,(((x - lastans[j]) % mod ) + mod ) % mod );
lastans[j] = x;
}
cout << cnt << endl;
}
signed main()
{
ios
int T=1;
// cin>>T;
while(T -- )
{
solve();
}
return 0;
}