P8932 [JRKSJ R7] Clock Paradox 题解
在博客园阅读 在洛谷博客阅读
Part 0 题意简述
原题这场月赛我唯一AC的题
给出一个字符串
具体变形:
Part 2 代码
根据上方分析,可以写出计算次数函数:
int calc(string s){
int cnt=1;
for(int i=1;i<s.length();i++)
if(s[i-1]!=s[i])
cnt++;
return cnt/2+cnt%2; // 这里等同于 ceil(cnt/2.0)
}
结合其他部分,写出完整代码:
#include<iostream>
#define reg register
using namespace std;
int q;
string s;
int p;
char c;
inline int calc(string s){
reg int cnt=1;
for(reg int i=1;i<s.length();i++)
if(s[i-1]!=s[i])
cnt++;
return cnt/2+cnt%2;
}
int main(){
ios::sync_with_stdio(0);
cin>>q>>s;
cout<<calc(s)<<endl;
while(q--){
cin>>p>>c;
s[p-1]=c;
cout<<calc(s)<<endl;
}
return 0;
}
但是,如果你把这段代码提交上去,你只能得到 50 分。为什么?
因为这段代码的时间复杂度高达
Part 3 优化
仔细观察上一段代码你就会发现它做了很多没用的事情。
在修改字符串时,子串数量
这里的维护代码:
cnt=cnt-((int)(s[p-2]!=s[p-1])+(int)(s[p-1]!=s[p]))+((int)(s[p-2]!=c)+(int)(c!=s[p]));
原理就是将原来函数内的循环展开,这里不过多解释,请自行思考。也可以修改函数使它支持单点维护但是我懒得写。
最终代码:
#include<iostream>
#define reg register
using namespace std;
int q;
string s;
int p;
char c;
int count(string s){
reg int cnt=1;
for(reg int i=1;i<s.length();i++)
if(s[i-1]!=s[i])
cnt++;
return cnt;
}
int main(){
ios::sync_with_stdio(0);
cin>>q>>s;
reg int cnt=count(s);
cout<<cnt/2+cnt%2<<endl;
while(q--){
cin>>p>>c;
cnt=cnt-((int)(s[p-2]!=s[p-1])+(int)(s[p-1]!=s[p]))+((int)(s[p-2]!=c)+(int)(c!=s[p]));
s[p-1]=c;
cout<<cnt/2+cnt%2<<endl;
}
return 0;
}