Codeforces Div2 2025.11.28

https://codeforces.com/contest/2170


B. Addition on a Segment

题目大意:
有一个长度为 \(n\) 初始全为 \(0\) 的序列 \(a\),并且给定一个确认的序列 \(b\) (\(0\leq b_i\leq n\)),每次可以选择一个区间 \([\ l,\ r\ ]\) 使得 \(a[l...r]\) 都加 \(1\),并且必须要操作 \(n\) 次使得 \(a\) 变成 \(b\),问 \(n\) 次操作中最大的 \(r-l+1\) 是多少

Solution:
因为必须要操作 \(n\) 次,而我们想要去最大化操作长度,所以让前 \(n-1\) 次操作只让某个数 \(+1\), 然后就可以让第 \(n\) 次操作的长度尽可能长了,并且操作的最大长度是原序列长度减去 \(0\) 的个数,因为显然不能对 \(0\) 进行加的操作,然后取一个 \(min\) 就好

namespace Solution{
    int n;
    void Main(){
        cin >> n;
        vector<int> a(n + 1);
        int zero = 0;
        For (i, 1, n) cin >> a[i];
        For (i, 1, n) if (a[i] == 0) zero++;
        int sum = 0;
        For (i, 1, n) sum += a[i];
        cout << min(sum - (n - 1), n - zero) << endl;
    }
};

C. Quotient and Remainder

题目大意:
有两个长度为 \(n\) 的数组 \(q\), \(r\), 给定一个 \(k\),选择两个数 \(x,y\) 满足 \(1\leq y\le x\leq k\),其中在 \(q\) 中删除 \(q_i=x/y\),在 \(r\) 中删除 \(r_j=x\%y\),问最多能删除几个数

Solution:
可以得出这个式子 \(q_j*y+r_i=x\),很显然 \(y> r_i\),而我们要让 \(x\) 尽可能的小,就不妨让 \(y=r_i+1\), 此时 \(q=(x-r)/(r+1)\),并且让 \(x\) 取到 \(k\),同时也让 \(q\) 取到能取到的最大。
如果最大的 \(r\) 能匹配到一个 \(q\),那么说明其余的 \(r\) 也可以用这个 \(q\),所以按照 \(r\) 从大到小排序

namespace Solution{
    int n, k;
    void Main(){
        cin >> n >> k;
        vector<int> q(n + 1), r(n + 1);
        For (i, 1, n) cin >> q[i];
        For (i, 1, n) cin >> r[i];
        // sort(r.begin() + 1, r.end(), greater<int>());
        multiset<int> Q(q.begin() + 1, q.end());
        int ans = 0;
        For (i, 1, n){
            int rr = r[i];
            int yy = (k - rr) / (rr + 1);
            auto it = Q.upper_bound(yy);
            if (it != Q.begin()){
                ans++;
                Q.erase(prev(it));
            }
        }
        cout << ans << endl;
    }
}
  

E. Binary Strings and Blocks

题目大意:
定义一个块为一个 \(01\) 字符串中连续的一部分, 一个块是美丽的当且仅当移除一个块后块的个数为奇数。
当前有 \(m\) 个约束 \(l_i,\ r_i\) 使得字符串在 \(s[l_i\rightarrow r_i]\) 是美丽的,问满足这些条件的长度为 \(n\) 的字符串的个数是多少

Solution:
首先一个字符串是美丽的只有它多于 \(1\) 个块就行
\(dp[\ i\ ]\) 表示长度为 \(i\) 的答案数,其中在第 \(i\) 位改变 \(01\) 也就是与第 \(i-1\) 位不一样。考虑所有的右端点小于 \(i\) 中左端点最大的 \(j\) 是多少。因为比如满足 \((3,7)\) 是美丽的,那么 \((2,8)\) 也一定是美丽的。所以可以从 \(j\) 转移到 \(i\),并且此时情况数要减去 \(j\) 前面的所有情况。如果没有左端点的话,那么就 \(*2\)
最后答案要 \(*2\) 因为我们目前只考虑了第一位是 \(1\) 的情况,第一位是 \(0\) 的话和是 \(1\) 是一样的。

namespace Solution{  
    int n, m;  
    void Main(){  
        cin >> n >> m;  
        vector<int> lmax(n + 5);  
        For (i, 1, m){  
            int l, r;   
            cin >> l >> r;  
            upmax(lmax[r], l);  
        }  
        For (i, 1, n){  
            upmax(lmax[i], lmax[i - 1]);  
        }  
        vector<int> dp(n + 5);  
        vector<int> sum(n + 5);  
        dp[0] = 1;  
        sum[0] = 1;  
        For (i, 1, n){  
            int tmp = sum[i - 1];  
            if (lmax[i]){  
                tmp = (tmp - sum[lmax[i] - 1] + mod) % mod;  
            }  
            dp[i] = tmp;  
            sum[i] = (sum[i - 1] + dp[i]) % mod;  
        }  
        cout << dp[n] * 2 % mod << endl;  
    }  
};
posted @ 2025-12-01 19:33  xyzEcho  阅读(11)  评论(0)    收藏  举报