Codeforces Round 906 (Div. 2)
文章目录
A. Doremy’s Paint 3
构造
给你一个数列,任意排序,使得相邻两项的和为k,判断是否存在这样的构造
b 1 + b 2 = b 2 + b 3 = … … = k b_1+b_2=b_2+b_3=……=k b1+b2=b2+b3=……=k
显然,b1如果固定,那么b2=k-b1,b3=b1
也就是数列a里面至多2个元素。
若数列a内有1个元素,则YES
若数列a内有两个元素,如果这两个元素能满足交替进行的数量那么也是YES
也就是:num1-num2<=1
这两个元素的个数只差不能大于1.
否则NO
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void slove(){
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++)cin>>a[i];
map<int,int> m;
for(int i=0;i<n;i++){
m[a[i]]++;
}
if(m.size()>2)cout<<"NO"<<endl;
else if(m.size()==1){
cout<<"YES"<<endl;
}
else{
auto it=m.begin();
it++;
int first=m.begin()->second;
int second=it->second;
if(m.begin()->second == it->second)cout<<"YES"<<endl;
else if (abs(first-second)==1)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
}
B. Qingshan Loves Strings
思维,构造
给一个数列a,元素只包含01,我们可以选择插入数组b 使得数列a的元素交替进行
请回答是否存在这样的构造
显然,当数列a中有两个连续的数的时候,我们才需要插入01
1、当连续的数是11,且数组b交替进行,且数组b两端是0 则yes
2、当连续的数是00,且数组b交替进行,且数组b的两端是1,则yes
所以步骤是:
1、判断数组a是否交替
2、特判数组a的长度为1的情况
3、求出数组a连续的地方,是11,还是00
4、判断数组b是否交替
5、当数组b两端为1
6、当数组b两端为0
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void slove(){
int n,m;
cin>>n>>m;
string s,t;
cin>>s>>t;
if(n==1){
cout<<"YES"<<endl;
return;
}
int jiji=0;
int ouou=0;
for(int i=0;i<n-1;i++){
if(s[i]==s[i+1]){
if(s[i]=='1')jiji++;
else ouou++;
}
}
if(jiji==0 and ouou==0){
cout<<"YES"<<endl;
return;
}
//检查t是否为好字符串
for(int i=0;i<m-1;i++){
if(t[i]==t[i+1]){
cout<<"NO"<<endl;
return;
}
}
//检查t字符串首尾是否相同
if(t[0]!=t[m-1]){
cout<<"NO"<<endl;
return;
}
// cout<<jiji<<' '<<ouou<<endl;
if(jiji!=0 and ouou!=0){
cout<<"NO"<<endl;
return;
}
else if(jiji!=0 and ouou==0){
if(t[0]=='1'){
cout<<"NO"<<endl;
return;
}
else{
cout<<"YES"<<endl;
return;
}
}
else if(jiji==0 and ouou!=0){
if(t[0]=='1'){
cout<<"YES"<<endl;
return;
}
else{
cout<<"NO"<<endl;
return;
}
}
else
cout<<"YES"<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
}
C. Qingshan Loves Strings 2
构造
和上一题不一样的是:
a i ≠ a k − i + 1 ( i = 1 , 2 , … , k ) ai≠a_{k−i+1} \ (i=1,2,…,k) ai=ak−i+1 (i=1,2,…,k)
也就是对称的情况
所以,这个数组的长度必须是偶数,不能是奇数,因为奇数会多出一个自己和自己配对的情况。
我们利用双端队列模拟并记录左端点右端点即可:
用vector记录操作的序列:
当队首=队尾,删除队首队尾
l++,r–
当队首!=队尾
考虑插入“01”
当队首队尾为1,那么插在队首的前面
将l-1插入vector
r+=2
当队首队尾为0,那么插在队尾的前面
将r插入vector
r+=2
最后输出vector即可
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define int long long
#define ll long long
const int N=1e5;
int a[N];
void slove() {
deque<char> q;
int n;
cin>>n;
char t;
for(int i=0;i<n;i++){
cin>>t;
q.push_back(t);
}
int cnt=0;
int l=1,r=n;
vector<int> ans;
while(q.size()){
if(cnt>300)break;
char f=q.front();
char b=q.back();
if(f!=b){
l++;
r--;
q.pop_back();
q.pop_front();
}
else{
if(f=='1' ){
ans.push_back(l-1);
q.push_front('1');
q.push_front('0');
r+=2;
}
else{
ans.push_back(r);
q.push_back('0');
q.push_back('1');
r+=2;
}
cnt++;
}
}
if(cnt>300 and q.size())cout<<-1<<endl;
else {
cout<<cnt<<endl;
for(auto i:ans)cout<<i<<' ';
cout<<endl;
}
}
signed main() {
// ios;
int T;
cin>>T;
while(T--){
slove();
}
}
r+=2;
}
cnt++;
}
}
if(cnt>300 and q.size())cout<<-1<<endl;
else {
cout<<cnt<<endl;
for(auto i:ans)cout<<i<<’ ';
cout<<endl;
}
}
signed main() {
// ios;
int T;
cin>>T;
while(T–){
slove();
}
}