P2109 最长递增子序列的数量

P2109\(\mathbf{} \begin{Bmatrix} \frac{{\Large SLOJ-P2109} }{{\color{Red}\Large Solution} }\mathbf{} {No.18} \end{Bmatrix}\times{}\) NeeDna

题意:给一个序列,求最长递增子序列的数量。

首先写一个朴素的暴力:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10,mod=1e9+7;
int n,a[N],mx,ans;
struct node{int x,s;}f[N];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		f[i].x=f[i].s=1;
		for(int j=1;j<=i;j++){
			if(a[i]>=a[j]){
				if(f[i].x<f[j].x+1){
					f[i].x=f[j].x+1;
					f[i].s=f[j].s;
				}
				else if(f[i].x==f[j].x+1){
					f[i].s=(f[i].s+f[j].s)%mod;
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(f[i].x>mx) mx=f[i].x,ans=f[i].s;
		else if(f[i].x==mx) ans=(f[i].s+ans)%mod;
	}cout<<ans;
	return 0;
}

然后发现这里:

	for(int i=1;i<=n;i++){
		f[i].x=f[i].s=1;
		for(int j=1;j<=i;j++){
			if(a[i]>=a[j]){
				if(f[i].x<f[j].x+1){
					f[i].x=f[j].x+1;
					f[i].s=f[j].s;
				}
				else if(f[i].x==f[j].x+1){
					f[i].s=(f[i].s+f[j].s)%mod;
				}
			}
		}
	}

满足:\(a[i]>a[j],i>j\) 是二维偏序,用树状数组维护即可(AI码风好看一点):

#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x&(-x))
using namespace std;
const int N=5e5+10, mod=1e9+7;
int n, a[N], mx, ans, b[N];
struct node{int x, s;} f[N], tr[N];

void upd(int x, int s, int i) {
    while (i < N) {
        if (tr[i].x == x) (tr[i].s += s) %= mod;
        else if (tr[i].x < x) tr[i].x = x, tr[i].s = s;
        i += lowbit(i);
    }
}

node sc(int i) {
    node t = {0, 0};
    while (i > 0) {
        if (tr[i].x > t.x) t = tr[i];
        else if (tr[i].x == t.x) (t.s += tr[i].s) %= mod;
        i -= lowbit(i);
    }
    return t;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i=1; i<=n; i++) cin >> a[i], b[i] = a[i];
    sort(b+1, b+n+1);
    for (int i=1; i<=n; i++) 
        a[i] = lower_bound(b+1, b+n+1, a[i]) - b;
    
    for (int i=1; i<=n; i++) {
        f[i] = {1, 1};
        node t = sc(a[i]-1);
        if (t.x + 1 > f[i].x) f[i] = {t.x + 1, t.s};
        else if (t.x + 1 == f[i].x) (f[i].s += t.s) %= mod;
        upd(f[i].x, f[i].s, a[i]);
    }
    
    for (int i=1; i<=n; i++) {
        if (f[i].x > mx) mx = f[i].x, ans = f[i].s;
        else if (f[i].x == mx) (ans += f[i].s) %= mod;
    }
    cout << ans % mod;
    return 0;
}
posted @ 2025-05-30 21:07  NeeDna  阅读(13)  评论(0)    收藏  举报