C. Traffic Light 10.23
https://codeforces.com/problemset/problem/1744/C
就普通题,先看看小蒟蒻自己的代码吧
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
//自己的代码test5超时
bool judge(int mid ,string &s,vector<int> position){
int Maxtime=0,midTime=0;
for(int i=0;i<position.size();i++){
int nt=position[i]+1;
if(nt>=s.size()) nt=0;
for(int j=nt;j<s.size();j++){
midTime++;
if(s[j]!='g'){
if(j==s.size()-1) j=-1;
continue;
}else{
Maxtime=max(Maxtime,midTime);
midTime=0;
if(Maxtime>=mid) return true;
break;
}
}
}
return Maxtime>=mid;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
char c;
string line;
vector<int> position;
cin>>n;
cin>>c;
cin>>line;
if(c=='g'){
cout<<"0\n";
}
else{
for(int i=0;i<line.size();i++){
if(line[i]==c){
position.push_back(i);
}
}
int mid;
int l=0,r=line.size();
while (l+1<r)
{
mid=(l+r)>>1;
if(judge(mid,line,position)){
l=mid;
}else{
r=mid;
}
}
cout<<l<<"\n";
}
}
return 0;
}
因为在judge函数中,查找距离时,时间复杂度到了O(n^2),很难接受了,导致test5数据超时。
我找ai询问,告诉我预处理‘g'的位置,不用预处理c的位置,我感觉两个位置都与处理一下,直接计算距离会更好,然后我就准备改代码了(这次代码就已经过了)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
bool judge(int mid ,string &s,vector<int>& position,vector<int>& g_pos){
int dist=-1;
for(auto i:position){
auto it=lower_bound(g_pos.begin(),g_pos.end(),i);
if(it!=g_pos.end()){
dist=*it-i;
}else{
dist=s.size()-i+g_pos[0];
}
if(dist>=mid) return true;
}
return dist>=mid;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
char c;
string line;
vector<int> position;
vector<int> g_pos;
cin>>n;
cin>>c;
cin>>line;
if(c=='g'){
cout<<"0\n";
}
else{
for(int i=0;i<line.size();i++){
if(line[i]==c){
position.push_back(i);
}else if(line[i]=='g'){
g_pos.push_back(i);
}
}
int mid;
int l=0,r=line.size();
while (l+1<r)
{
mid=(l+r)>>1;
if(judge(mid,line,position,g_pos)){
l=mid;
}else{
r=mid;
}
}
cout<<l<<"\n";
}
}
return 0;
}
最后,ai告诉我了一种线性的办法
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
int n;
char c;
string line;
cin >> n;
cin >> c;
cin >> line;
if (c == 'g') {
cout << "0\n";
continue;
}
// 将字符串复制一份来模拟环形
line = line + line;
int maxWait = 0;
int lastG = -1;
// 从后往前遍历
for (int i = line.length() - 1; i >= 0; i--) {
if (line[i] == 'g') {
lastG = i;
}
if (lastG != -1 && i < n && line[i] == c) {
maxWait = max(maxWait, lastG - i);
}
}
cout << maxWait << "\n";
}
return 0;
}
还有一种最高效的二分,ai说的
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
int n;
char c;
string s;
cin >> n >> c >> s;
if (c == 'g') {
cout << "0\n";
continue;
}
// 将字符串复制一份处理环形
s = s + s;
vector<int> g_pos;
for (int i = 0; i < 2 * n; i++) {
if (s[i] == 'g') {
g_pos.push_back(i);
}
}
// 二分答案
int left = 1, right = n, ans = 0;
while (left <= right) {
int mid = (left + right) / 2;
bool valid = false;
for (int i = 0; i < n; i++) {
if (s[i] == c) {
// 在g_pos中查找第一个 >= i + mid 的g
auto it = lower_bound(g_pos.begin(), g_pos.end(), i + mid);
if (it != g_pos.end() && *it - i <= n) {
valid = true;
break;
}
}
}
if (valid) {
ans = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
cout << ans << "\n";
}
return 0;
}
对于可能循环的问题,很好的办法就是写两遍,就是s=s+s
浙公网安备 33010602011771号