Codeforces Round 195 (Rated for Div. 2)

CF爆炸了没办法提交评测说是

image

A. Perfect Sandwiches #

Monocarp 有 \(a\) 片奶酪和 \(b\) 片香肠。他想用这些为他的朋友们制作尽可能多份的三明治。

Monocarp 非常节俭,因此他必须用光所有的 \(a\) 片奶酪和所有的 \(b\) 片香肠来制作三明治,不能有任何剩余。此外,他制作三明治有以下规定:

  • 每份三明治必须至少包含一片奶酪和至少一片香肠;
  • 每片奶酪和每片香肠都必须且只能放在一份三明治上;
  • 对于每份三明治,奶酪的片数必须严格大于香肠的片数。

请帮助 Monocarp 确定他最多能制作多少份三明治,或者判断是否无法按照这些规定分配所有的切片。

输入
第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\))—— 测试用例的数量。

每个测试用例的唯一一行包含两个整数 \(a\) 和 \(b\)(\(1 \le a, b \le 100\))—— 分别代表奶酪和香肠的片数。

输出
对于每个测试用例,输出一个整数 —— 能够制作的最大三明治数量。如果无法按照所述规定分配所有切片,则输出 -1。

容易得到有解的限制条件是 \(a>b\)

在有解的基础上,做 \(k\) 份三明治,最少需要 \(b+k\) 片奶酪。也就是 \(a\gt b+k\),由此解出 \(k\) 的最大值。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int a,b;cin>>a>>b;
        cout<<(a<=b?-1:min(b,a-b))<<endl;
    }
}

B. Replace and Compress #

给你一个长度为 \(n\) 的字符串 \(s\),仅由字符 0 和/或 1 组成。你需要执行恰好一次操作,该操作包含两个步骤:

  1. 从索引 \(2\) 到 \(n-1\)(包含两端)中至多选择一个字符,并将其替换为相反的字符:0 变 1 或 1 变 0。你可以选择不改变任何字符。字符串的第一个和最后一个字符不能被改变;
  2. 将每一段连续的相同字符组成的极大块替换为一个该字符。

如果一段字符无法通过向左或向右添加相同字符来扩展,则称其为极大块。例如,在第二步之后,字符串 100111011 将变为 10101。

请计算执行此操作后可以得到的不同字符串的数量。

输入
第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\))—— 测试用例的数量。

每个测试用例包含一行,包含一个仅由字符 0 和 1 组成的字符串 \(s\)(\(3 \le |s| \le 3 \cdot 10^5\))。

关于输入的附加限制:

  • 所有测试用例中字符串 \(s\) 的长度之和不超过 \(3 \cdot 10^5\)。

输出
对于每个测试用例,输出一个整数 —— 执行操作后可以得到的不同字符串的数量。

注意到我们不能改变首位字符,并且最后的字符串内一定没有连续相同的字符。

这就意味着:最终,相同长度的字符串一定是同一个字符串。原问题也即求共可能会出现多少不同长度的字符串。

除了不做修改出现的字符串以外。还可能有

  1. 通过把一个单独的数字替换为与其左右相同的数字使长度减少 \(2\)。 只需判断是否存在单独数字即可。
  2. 通过把长度至少为 \(3\) 的连通块中间的数字反转使长度增加 \(2\)。 只需判断是否存在连通块长度大于等于 \(3\) 即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	string s;
	cin>>t;
	while(t--){
		cin>>s;
        s=' '+s;
        bool f1=false,f2=false;
        int ans=1;
		for(int i=2;i<s.size()-1;i++){
		    if(s[i]!=s[i-1]&&s[i]!=s[i+1]) f1=true;
            else if(s[i]==s[i-1]&&s[i]==s[i+1]) f2=true;
        }
		ans+=f1+f2;
		cout<<ans<<endl;
	}
}

C. Subarrays #

Monocarp 有一个包含 \(n\) 个正整数的数组 \(a\)。他还有一个最喜欢的整数 \(k\)(\(k < n\))。

数组中索引从 \(l\) 到 \(r\)(\(1 \le l \le r \le n\))的连续元素序列被称为一个子数组。如果满足以下条件,Monocarp 称一个子数组是 \(k\)-平衡的(\(k\)-balanced):

  • 子数组从 \(l\) 到 \(r\)(包含两端)的所有元素之和能被 \(k\) 整除;
  • 这个子数组的长度严格大于 \(k\)(即 \(r - l + 1 > k\))。

请帮助 Monocarp 确定数组 \(a\) 中 \(k\)-平衡子数组的总数。

输入
第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\))—— 测试用例的数量。

接下来是测试用例的描述。

每个测试用例的第一行包含两个整数 \(n\) 和 \(k\)(\(1 \le k < n \le 2 \cdot 10^5\))—— 数组 \(a\) 中的元素数量以及整数 \(k\)。

每个测试用例的第二行包含 \(n\) 个整数 \(a_1, a_2, \dots, a_n\)(\(1 \le a_i \le 10^9\))—— 数组 \(a\) 的元素。

关于输入的附加限制:

  • 所有测试用例中 \(n\) 的总和不超过 \(2 \cdot 10^5\)。

输出
对于每个测试用例,输出一个整数 —— 数组 \(a\) 中 \(k\)-平衡子数组的数量。

考虑一下处理一个前缀和。那么 \(\sum_{i=x}^{y}a_i\equiv 0\pmod k\) 即为 \(s_{y}-s_{x-1}\equiv 0\pmod k\),\(s_{y}\equiv s_{x-1}\pmod k\)

#include<bits/stdc++.h>
using namespace std;
int n,k;
int cnt[200001],a[200001],s[200001];
int main(){
    int t;cin>>t;
    while(t--){
        cin>>n>>k;
        int ans=0;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            s[i]=s[i-1]+a[i];
            cnt[s[i]%k]=0;
            //cout<<s[i]%k<<" ";
        }
        //cout<<endl;
        for(int i=1;i<=n;++i){
            if(i-k-1>=0) cnt[s[i-k-1]%k]++;
            ans+=cnt[s[i]%k];
        }
        cout<<ans<<endl;
    }
}

D. Caveman #

Monocarp 画了一个包含 \(n\) 个顶点和 \(m\) 条边的无向图。他想将每个顶点染成红色或蓝色,使得每个顶点至少有一个颜色不同的邻居。他需要计算有多少种符合条件的染色方案。

Monocarp 是一个原始人:他只知道数字 \(1\)、\(2\) 和“许多”(任何大于 \(2\) 的数)。他不知道零的概念,所以如果没有任何合法的染色方案,他的大脑就会宕机。

请用 Monocarp 的语言帮助他统计合法的染色方案数。如果在至少一个顶点上颜色不同,则两个染色方案被视为不同的。

输入
第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\))—— 测试用例的数量。

每个测试用例的第一行包含两个整数 \(n\) 和 \(m\)(\(3 \le n \le 3 \cdot 10^5\);\(0 \le m \le \min\left(\frac{n(n-1)}{2}, 3 \cdot 10^5\right)\))—— 顶点和边的数量。

接下来 \(m\) 行,每行包含两个整数 \(u_i\) 和 \(v_i\)(\(1 \le u_i, v_i \le n\))—— 第 \(i\) 条边连接的两个顶点的编号。图中没有自环或重边。

关于输入的附加限制:

  • 所有测试用例中 \(n\) 的总和不超过 \(3 \cdot 10^5\);所有测试用例中 \(m\) 的总和也不超过 \(3 \cdot 10^5\)。

输出
对于每个测试用例,在单独的一行中输出:

  • 1 或 2,如果合法染色方案的数量分别等于 1 或 2;
  • Many,如果合法染色方案的数量大于 2;
  • Brain Melt,如果没有合法的染色方案。

依旧脑筋急转弯这一块

一个一个考虑。先考虑方案为 \(0\) 的情况。可以发现仅当图不连通的时候可能无解。

方案为 \(1\) 的情况:不可能存在。证明:将合法方案取反,一定存在另一个解。或者说,方案数一定为偶数。

方案为 \(2\) 的情况:先考虑方案大于 \(2\) 的情况。设点 \(x,y\) ,假如 \(x\) 和 \(y\) 都有各自相邻的点 \(x_0,y_0\)。可以令 \(x_0=y_0,x=y\),也可以令 \(x_0=y,x=y_0\),结合对称性则至少有四种状态。如果 \(x_0,y_0\) 任一个不存在,那么不可能有 \(x=y\)。所以,如果我们想限制只存在 \(2\) 种方案,那么必须让任意两个点都不让 \(x_0,y_0\) 同时存在。也就是图的层数不超过 \(2\)。判断即可。

#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int>e[300001];
int vis[300001],d[300001];
int cnt;
void dfs(int u){
    vis[u]=1;
    cnt++;
    for(auto v:e[u]){
        if(vis[v]) continue;
        dfs(v);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;++i){
            vis[i]=0;
            d[i]=0;
            e[i].clear();
        }
        for(int i=1;i<=m;++i){
            int u,v;
            cin>>u>>v;
            d[u]++,d[v]++;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        int flag=0;
        for(int i=1;i<=n;++i){
            if(!vis[i]){
                cnt=0;
                dfs(i);
                if(cnt==1){
                    flag=1;
                    break;
                }
            }
        }
        if(flag){
            cout<<"Brain Melt"<<'\n';
            continue;
        }
        flag=0;
        int res=0;
        for(int i=1;i<=n;++i){
            if(d[i]==n-1) res++;
            else if(d[i]!=1){
                flag=1;
                break;
            }
        }
        if(flag||res!=1){
            cout<<"Many"<<'\n';
            continue;
        }
        cout<<2<<'\n';
    }
}

E. Good Substrings #

给你一个长度为 \(n\) 的字符串 \(s\),仅由数字组成。

\(s\) 的子串是其字符的一个连续子序列。如果一个子串 \(s_{l \dots r}\) 包含字符串 2025 作为子序列,且不包含字符串 2026 作为子序列,则该子串是坏的。否则,该子串是好的。例如,字符串 2025、72707275、20625 是坏的,但字符串 20256、2026、777、1290723576 是好的。

对于从 \(1\) 到 \(n\) 的每个索引 \(i\),计算包含它的好子串的数量。换句话说,对于从 \(1\) 到 \(n\) 的每个索引 \(i\),计算整数对 \(l, r\) 的数量,使得 \(1 \le l \le i \le r \le n\) 且子串 \(s_{l \dots r}\) 是好的。

输入
第一行包含一个整数 \(t\)(\(1 \le t \le 10^4\))—— 测试用例的数量。

每个测试用例的第一行包含一个整数 \(n\)(\(1 \le n \le 3 \cdot 10^5\))。

第二行包含一个长度为 \(n\) 的字符串 \(s\),由数字组成。

关于输入的附加限制:所有测试用例中 \(n\) 的总和不超过 \(3 \cdot 10^5\)。

输出
对于每个测试用例,输出 \(n\) 个整数。第 \(i\) 个整数应等于包含索引 \(i\) 的好子串的数量。

考虑每个位置的坏字串个数。

肯定是要去找 2025 和 2026 第一次出现在哪里的。这个的话我们可以对每个位置 \(i\) 维护其后方第一个 2 在哪,同理维护 2 后面第一个 0,以此类推。设 2025,2026 的末位下标分别为 \(a,b\),那么当取 \([a,b-1]\) 内的字符串时,则是一个坏串。总的坏串数量是 \(b-a\)

不过答案要求区间答案。因此考虑一下差分。不过有一点需要注意的是,这样会把 \(a\) 前面的答案也统计进来。这个比较好处理,统计答案的时候减去 \(a\) 前面的累计差分就行了。最后,以 \(i\) 为左端点的总字串数量为 \(i(n-i+1)\),减一下就好了。

差分以后累计复杂度太高。直接用线段树维护前缀和即可。

cf爆炸了,代码等评测好了再粘


posted @ 2026-10-18 15:29  HaneDaniko  阅读(26)  评论(1)    收藏  举报