日常刷题2025-3-13
日常刷题2025-3-13
经验+1
题目求最大值最小,或者最小值最大都可以考虑二分。一般都是二分配一个贪心。
配一道比较难判断出二分的题https://codeforces.com/contest/2070/problem/C
C. Kevin and Binary Strings
rating:1200
思路:小巧思
为了使结果的位数足够多,我们选择的一个子串应该尽可能长,所以就是整个字符串。考虑如何选择第二个字符串能让结果最大?
结果要大,则字符串中的1一定要多,且1的位置最好是要高一点。我们找到第一个字符串第一个不为1的位置,把它变为1是最好的,假设在p位置。则我们需要一个长度为n-p的字符串。整个字符串中每个长度为n-p的字符串都有可能,所以我们要枚举所有情况。
枚举了所以情况如何判断哪种情况更优呢?发现此题的数据范围比较小,假设我们枚举了一个长度为n-p的字符串,我们暴力计算出它与第一个选出的字符串XOR后的字符串,我们发现,字符串的比较方式刚好适用于二进制数的比较方式。这样我们就可以根据选出来的字符串与第一个字符串XOR后得到的新字符串的相互比较来判断哪种选择方式更优。
代码
#include <bits/stdc++.h>
typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;
std::string ck(std::string a, std::string b){
int n=a.size();
std::string ret(n,'0');
for(int i=0;i<n;i++){
if(a[i]!=b[i]) ret[i]='1';
}
return ret;
}
void solve(){
std::string s; std::cin>>s;
int n=s.size();
int p;
for(p=0;p<n&&s[p]=='1';p++);
if(p==n){
std::cout<<1<<' '<<n<<' '<<1<<' '<<1<<'\n';
return;
}
int len=n-p;
std::string x=s.substr(p,len);
std::string ans;
int ansl=0,ansr=len-1;
for(int i=0;i+len-1<n;i++){
std::string t=s.substr(i,len);
if(i==0){
ans=ck(x, t);
}else{
std::string tmp=ck(x,t);
if(tmp>ans){
tmp=ans;
ansl=i;
ansr=i+len-1;
}
}
}
std::cout<<1<<' '<<n<< ' '<<ansl+1<<' '<<ansr+1<<'\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
std::cin >> t;
for (i = 0; i < t; i++){
solve();
}
return 0;
}

浙公网安备 33010602011771号