这里写目录标题
题目链接
A. Déjà Vu
思路1
当字符串里面存在a以外的字母,肯定可以构造一个非回文字符串,在将要插入的位置的对称位置看看是不是a,不是a就插入,就可以构造一个非回文字符串.
代码1
#include<bits/stdc++.h>
using namespace std;
void solve()
{
string s;
cin>>s;
for(int i=0;i<s.size();i++)
{
if(s[i]!='a')
{
puts("YES");
int was=1;
for(int j=0;j<s.size();j++)
{
if(s[s.size()-j-1]!='a')
{
if(was)
{
// cout<<i;
cout<<"a";
was=0;
}
}
cout<<s[j];
}
cout<<endl;
return;
}
}
puts("NO");
}
int main()
{
int n;
cin>>n;
while(n--)solve();
return 0;
}
思路2
只需判断首尾插入a就知道能不能构成非回文字符串,.大佬写的,我不知道为什么.
代码2
#include<bits/stdc++.h>
using namespace std;
bool check(string s)
{
int n=s.size();
for(int i=0;i<n/2;i++)
if(s[i]!=s[n-i-1])
return false;
return true;
}
void solve()
{
string s;
cin>>s;
if(check(s+'a'));
else
{
cout<<"YES"<<endl;
cout<<s+'a'<<endl;
return ;
}
if(check('a'+s));
else
{
cout<<"YES"<<endl;
cout<<'a'+s<<endl;
return ;
}
cout<<"NO"<<endl;
}
int main()
{
int n;
cin>>n;
while(n--)solve();
return 0;
}
B. Flip the Bits
思路
每次操作需要判断区间内0与1个数是否相等,所以要预处理前缀a[i]表示字符串0~i中0与1的个数相等;然后再从后往前遍历,用个变量v记录操作次数,操作次数为奇数即v=1,则与两个字符串对应字母是否相等的状态取反;为偶数即v=0,则不变;每次俩字符串对应字母不同就改变v(通过v^=1改变);
代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
bool a[N];
void solve()
{
int n;
cin>>n;
string s,t;
cin>>s>>t;
memset(a,0,sizeof a);
int cnt1=0,cnt0=0;
for(int i=0;i<n;i++)
{
if(s[i]=='1')cnt1++;
else cnt0++;
if(cnt1==cnt0)a[i]=true;
}
bool v=false;
for(int i=n-1;i>=0;i--)
{
if(s[i]!=t[i])
{
if(!v)
{
v==0?v=1:v=0;// 等价于v^=1
if(!a[i])
{
cout<<"NO"<<endl;
return ;
}
}
}
else
{
if(v)
{
v==0?v=1:v=0;
if(!a[i])
{
cout<<"NO"<<endl;
return ;
}
}
}
}
cout<<"YES"<<endl;
return ;
}
int main()
{
int n;
cin>>n;
while(n--)solve();
return 0;
}
C. Balance the Bits
思路
很明显如果01字符串首尾有一个0是不能构造合法括号的;题目说的n是偶数,如果字符串1的个数为奇数,那么0的个数也为奇数,这样的话怎么都构造不出合法括号…所以字符串1的个数必须为偶数.
如果能构造,设有cnt个1,则前cnt/2个1全构造成左括号(贪心),0则是交换构造;
代码
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin>>n;
string s;
string a,b;
cin>>s;
int cnt=0;
for(auto t:s)cnt+=(t=='1');
if(s[0]!='1'||s[n-1]!='1'||cnt&1)
{
cout<<"NO"<<'\n';
return ;
}
bool v=false;
cout<<"YES"<<'\n';
for(auto c:s)
{
if(c=='1')
{
if(cnt>0)a+='(',b+='(';
else a+=')',b+=')';
cnt-=2;
}
else
{
if(v)a+='(',b+=')';
else a+=')',b+='(';
v^=1;
}
}
cout<<a<<'\n';
cout<<b<<'\n';
}
int main()
{
int n;
cin>>n;
while(n--)solve();
return 0;
}
D.我不会D题,不想补了
E.Travelling Salesman Problem
思路
贪心题, 根据题目描述,显然 cost 最小为
∑
i
=
0
n
−
1
a
[
i
]
.
c
\sum_{i=0}^{n-1}a[i].c
∑i=0n−1a[i].c ;
从 a[i].a 最小的出发,遍历其他所有点, 设a[0].a为a[i].a中最小的点
(若 a[0].a == a[i].a ,则 a[0].c < a[i].c ) ; 则只花费 a[0].c 可到达的点为 a[i].a <= a[0].a + a[0].c 的点; 反之, 花费需要加上 ( a[0].a + a[0].c ) - a[i].a );到达a[i]这个点后,判断a[i]只花费 a[i]可到达的点与a[0]可到达的点的大小 ( 即 a[i].a + a[i].c > or <= a[0].a + a[0].c ) ;然后更新可到达的点的大小;重复上面的步骤;
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int M=1e5+10;
struct node{
int a,c;
}ai[M];
bool cmp(const node &x,const node &b)
{
if(x.a==b.a)return x.c<b.c;
return x.a<b.a;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>ai[i].a>>ai[i].c;
sort(ai,ai+n,cmp);
int ans=ai[0].c;
int v=ai[0].a+ai[0].c;
for(int i=1;i<n;i++)
{
ans+=ai[i].c;
if(ai[i].a>v)
{
ans+=ai[i].a-v;
}
v=max(v,ai[i].a+ai[i].c);
}
cout<<ans<<'\n';
return 0;
}
这篇博客详细解析了Codeforces Round #712 (Div. 2)的比赛题目,包括A. Déjà Vu、B. Flip the Bits和C. Balance the Bits的思路和解决方案。对于A题,提出了两种构造非回文字符串的方法;B题通过预处理和后向遍历来解决位翻转问题;C题通过判断1的个数和贪心策略构造合法括号。D题未提供解答,E题是关于Travelling Salesman Problem的贪心策略解析。

855

被折叠的 条评论
为什么被折叠?



