1 条题解

  • 0
    @ 2025-8-23 20:06:39

    O(M)O(M) 桶+后缀和

    问题转化:由于只能使用两种颜色,且同色必须连续,整个围栏会被分成两个连续段,每段一种颜色。

    前缀和处理:

    计算后缀和数组sum,其中sum[i]表示最大涂刷数量大于等于i的颜色种类数。

    计算方案数:

    遍历所有可能的分段点i(1≤i≤m-1),将围栏分为长度为i和m-i的两段。

    对于分段点i,需要找到两种颜色,一种能涂刷至少i块木板,另一种能涂刷至少m-i块木板。

    方案数为:能涂刷至少i块的颜色数 × 能涂刷至少m-i块的颜色数 - 重复计算的部分。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define endl '\n'
    #define pb push_back
    #define pp pop_back
    #define io() ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
    const int N = 2e5 + 5;
    int a[N], sum[N];
    void solve() {
    	memset(sum, 0, sizeof sum);
    	int m, n;
    	cin >> m >> n;
    	for (int i = 1; i <= n; i++) {
    		cin >> a[i];
    		sum[a[i]]++;
    	}
    	for (int i = m; i >= 1; i--) {
    		sum[i] += sum[i + 1];
    	}
    	long long ans = 0;
    	for (int i = 1; i < m; i++) {
    		int x = min(i, m - i), y = max(i, m - i);
    		ans += sum[x] * sum[y] - sum[y];
    //		cout << x << " " << y << " : " << sum[x] * sum[y] - sum[y] * sum[y] << endl;
    	}
    	cout << ans << endl;
    }
    
    signed main() {
    	// io();
    	int _ = 1;
    	cin >> _;
    	for (; _--;) solve();
    	return 0;
    }
    
    • 1

    信息

    ID
    528
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    2
    上传者