1 条题解

  • 0
    @ 2025-3-26 9:32:54
    • 技能最多触发一次。

    • 要使得触发技能时,种类数尽可能多,然后使用价值最大的牌。

    • 若某种牌数量超出一张,使用它不会减少种类数。统计总共能以此法使用 m=i=1n(ai1)m=\sum_{i=1}^n (a_i-1) 张。

    • 若触发技能时,该次使用的牌消耗后还有剩余,那么:

      • 统计满足 ai>1a_i>1 的最大 bib_i,记为 maxvmaxv
      • 接下来最大化种类数,额外收益即种类数与 maxvmaxv 的乘积。
      • mnm\ge n,先使用 n1n-1 次并为该类别保留两张,第 nn 次使用该类别牌,种类数为 nn
      • m<nm<n
        • nmn-m22 的倍数,先使用 m1m-1 次并为该类别保留两张,接下来每次使用都将使得总类别减少 11,设使用 kk 次,最后一次再使用该类别,那么使用次数 m1+k+1m-1+k+1 等于剩余类别 nkn-k,故 2k=nm2k=n-m,则种类数为 nkn - k
        • 否则,可以先使用 m2m-2 次并为该类别保留两张, 故 m2+k+1=nk2k=nm1m-2+k+1=n-k\to 2k=n-m-1,则种类数为 nkn - k
    • 若触发技能后,允许该次使用的牌为最后一张,则记录 bib_i 的最大值,使用这种牌触发技能。额外收益的讨论类似。

    • 时间复杂度是 Θ(n)\Theta(n)

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    
    void solve() {
    	int n; cin >> n;
    	vector<int> a(n), b(n);
    	int extra_num = 0;
    	for(int i = 0; i < n; i++) {
    		cin >> a[i];
    		extra_num += a[i] - 1;
    		extra_num = min(n, extra_num);
    	}
    	for(int i = 0; i < n; i++) {
    		cin >> b[i];
    	}
    	
    	// 若希望使用后, 该牌剩余一张以上
    	int maxv = 0;
    	long long ans = 0;
    	for(int i = 0; i < n; i++) {
    		if(a[i] > 1) maxv = max(maxv, b[i]);
    	}
    	
    	// 先使用 extra 张, 再消耗 k 种类, 最后正好剩 extra + k 类
    	// extra + 2k = n
    	
    	if(extra_num || (n % 2 == 0)) {
    		int k = (n - extra_num + 1) / 2;
    		ans = max(ans, (n - k) * (long long) maxv);
    	}
    	
    	// 若使用后, 该牌可以消失
    	maxv = *max_element(b.begin(), b.end());
    	if(extra_num || (n % 2 == 0)) {
    		int k = max(1, (n - extra_num + 1) / 2);
    		ans = max(ans, (n - k) * (long long) maxv);
    	}
    	
    	cout << ans << '\n';
    }
    
    int main() {
    	ios::sync_with_stdio(false); cin.tie(nullptr);
    	int t; cin >> t; while(t--) solve();
    	return 0;
    }
    
    
    • 1

    信息

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