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;
}

浙公网安备 33010602011771号