P3970 [TJOI2014]上升子序列(BIT&DP)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3970 [TJOI2014]上升子序列(BIT&DP)相关的知识,希望对你有一定的参考价值。
P3970 [TJOI2014]上升子序列(BIT&DP)
求长度至少为2不同的 L I S LIS LIS个数。
- 忽略掉长度至少为2,且不同的条件。
令 f i f_i fi表示以 a i a_i ai的 L I S LIS LIS个数。
则有 : f i = ( ∑ a j < a i f j ) + 1 , ( j < i ) \\large f_i=(\\sum\\limits_{a_j<a_i} f_j)+1,(j<i) fi=(aj<ai∑fj)+1,(j<i)
a n s = ∑ i = 1 n f i \\large ans=\\sum\\limits_{i=1}^n f_i ans=i=1∑nfi
求前缀和可用 B I T BIT BIT优化到 l o g n logn logn。
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
因为 ∣ a i ∣ ≤ 1 0 9 |a_i|\\le 10^9 ∣ai∣≤109 ,考虑离散化即可。
接下来处理不同和**长度至少为 2 2 2**的条件。
- 不同
我们对于每个相同的 a i a_i ai,记录上一次的答案。
假设 a j = a i , j < i , l a s t a n s = f j \\large a_j=a_i,j<i,lastans=f_j aj=ai,j<i,lastans=fj
显然 f i \\large f_i fi包括 f j \\large f_j fj ,即答案会重复。
所以 f i \\large f_i fi应该减去 f j \\large f_j fj。
所以
f i = ( ∑ a j < a i f j ) + 1 − l a s t a n s , ( j < i ) \\large f_i=(\\sum\\limits_{a_j<a_i} f_j)+1-lastans_{},(j<i) fi=(aj<ai∑fj)+1−lastans,(j<i)
l a s t a n s i + = f i \\large lastans_{i}+=f_i lastansi+=fi
- 长度为2
最后 ∑ i = 1 m f i − m \\large \\sum\\limits_{i=1}^m f_i-m i=1∑mfi−m
m \\large m m是离散化后的长度,也就是长度为 1 1 1的答案。
// Problem: P3970 [TJOI2014]上升子序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3970
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-26 18:05:09
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
int n,lst[N],a[N],b[N],m;
ll s;
struct BIT{
#define lowbit(x) x&(-x)
#define il inline
ll s[N];
int n;
il void upd(int x,int v){
while(x<=m){
s[x]=(s[x]+v)%mod;x+=lowbit(x);
}return;
}
il ll que(int x){
ll ans=0;
while(x){
ans=(ans+s[x])%mod;x-=lowbit(x);
}return ans;
}
}T;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
ll x=(T.que(a[i]-1)+1-lst[a[i]])%mod;
T.upd(a[i],x);
lst[a[i]]+=x;
}
printf("%lld\\n",(T.que(m)-m+mod)%mod);
return 0;
}
以上是关于P3970 [TJOI2014]上升子序列(BIT&DP)的主要内容,如果未能解决你的问题,请参考以下文章