1 条题解

  • 0
    @ 2025-10-3 17:04:06

    每一种宠物,要么是花 aia_i 购买的,要么是通过若干次转换获得的。显然答案就是购买的 ai\sum a_i 加上 xx 乘所需转换次数的最大值。

    枚举 kk 表示转换次数的最大值,现在我们要选出若干个 aia_i 直接购买,要找出一个最优策略。

    然后我开始饭糖了

    我是这么想的:

    显然每一个没被选的都要从它前面第一个被选的地方推过来,考虑 DP。设计 dpidp_i 表示前 ii 个中,第 ii 个必选且满足条件的最小值。 dpi=dpj+aj(ij1)+aidp_i=dp_j+a_j*(i-j-1)+a_i

    首先我目测这玩意没法斜率优化,其次他是一个环,我不会求答案,但我知道绝对不是 dpn+idpidp_{n+i}-dp_i

    正解

    std的思路是,还是先枚举 kk,然后每一个 ii 从前面 kk 个找最小值。

    这么做保证了是从上一个选择的地方过来的。

    证明如下

    (感谢大佬 @

    考虑反证。假设 x<y<ix<y<i,现在假设 aia_iaxa_x 转移过来,且 aya_y 选了。

    aia_iaxa_x 而不是 aya_y 转移过来,说明 ax<aya_x<a_y,且 xxii 之间可以不选别的。这样 aya_y 可以从 axa_x 转移过来,不需要选 aya_y,假设不成立。证明毕。


    然后这个最小值可以使用 ST 表处理。但注意到这一步的决策包含了上一步的决策,所以我们可以直接维护一个 miimi_i 表示 iikk 个的最小值。

    时间复杂度 Θ(n2)\Theta(n^2)

    #include<bits/stdc++.h>
    #define int long long
    #define R(x) x=read()
    using namespace std;
    inline int read() {
    	int x=0,y=1;
    	char e=getchar();
    	while(e>'9'||e<'0') {
    		if(e=='-')y=-1;
    		e=getchar();
    	}
    	while(e>='0'&&e<='9') {
    		x=(x<<3)+(x<<1)+(e^'0');
    		e=getchar();
    	}
    	return x*y;
    }
    const int N=2005;
    int n,x,a[N],ans;
    int mi[N];
    signed main() {
    	freopen("collection.in","r",stdin);
    	freopen("collection.out","w",stdout);
    	R(n),R(x);
    	for(int i=1; i<=n; ++i) {
    		R(a[i]);
    		mi[i]=a[i];
    		ans+=a[i];
    	}
    	for(int k=1; k<=n; ++k) {
    		int res=k*x;
    		for(int i=1; i<=n; ++i) {
    			mi[i]=min(mi[i],a[(i+n-k-1)%n+1]);
    			res+=mi[i];
    		}
    		ans=min(ans,res);
    	}
    	cout<<ans<<"\n";
    	return 0;
    }
    
    • 1

    信息

    ID
    448
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    (无)
    递交数
    16
    已通过
    6
    上传者