2023NOIP A层联测9 T3 天竺葵

2023NOIP A层联测9 T3 天竺葵

题面及数据范围

Ps:连接为accoderOJ。

看题大概是一个最长上升子序列的带权版本,于是想到 dp。

d p [ i ] [ j ] dp[i][j] dp[i][j] 为到第 i i i 项,选出 j j j 个数的 c j c_j cj 最小值,不难想到转移:
d p [ i ] [ j ] = min ⁡ ( d p [ i − 1 ] [ j ] , a [ i ]   ( a [ i ] > d p [ i − 1 ] [ j ] ∗ b [ j ] )   ) dp[i][j]=\min(dp[i-1][j],a[i]\ (a[i]>dp[i-1][j]*b[j])\ ) dp[i][j]=min(dp[i1][j],a[i] (a[i]>dp[i1][j]b[j]) )

若任意 b i > 1 b_i>1 bi>1 ,那么答案长度不超过 50 50 50 个(每次 c i c_i ci 都要比至少 c i − 1 ∗ b i − 1 c_{i-1}*b_{i-1} ci1bi1 大,而 b i − 1 b_i-1 bi1 大于 1 1 1 所以可以很快接近 a i a_i ai 的上限)。

进一步,发现 d p [ i ] dp[i] dp[i] 具有随 j j j 上升的单调性,所以把 d p [ i ] dp[i] dp[i] 通过 a [ i ] a[i] a[i] 分为两部分,第一部分 d p [ i ] [ j ] dp[i][j] dp[i][j] 均小于 a [ i ] a[i] a[i],第二部分 d p [ i ] [ j ] dp[i][j] dp[i][j] 均大于等于 a [ i ] a[i] a[i]

那么对于小于 a [ i ] a[i] a[i] 的那一部分 d p [ i ] [ j ] dp[i][j] dp[i][j] 根据转移方程肯定等于 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j],对于大于等于的那一部分 d p [ i ] [ j ] dp[i][j] dp[i][j] 除第一个位置外,其他的位置的 d p [ i ] [ j ] ∗ b [ j ] dp[i][j]*b[j] dp[i][j]b[j] 一定有 a [ i ] ≤ d p [ i ] [ j ] ∗ b [ j ] a[i] \leq dp[i][j]*b[j] a[i]dp[i][j]b[j],所以可以更新的位置只有一个,那么每次更新一个位置即可。

CODE
#include
using namespace std;

#define int long long

const int maxn=1e6+5;

int n,ans;
int a[maxn],f[maxn],b[maxn];

signed main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&b[i]);

    memset(f,0x7f,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        int pos=lower_bound(f+1,f+n+1,a[i])-f;
        if(a[i]>b[pos-1]*f[pos-1]) f[pos]=min(f[pos],a[i]);
    }

    for(int i=1;i<=n;i++) if(f[i]!=f[0]) ans=i;
    printf("%lld",ans);
}

你可能感兴趣的:(算法,数据结构,c++,动态规划)