文章目录
The Third Week
耐心和恒心总会得到报酬的。 ————爱因斯坦
一、前言
同上啊周二天梯,有一道题卡了很久但其实不太有价值,还导致我后面的题目做崩了,所以ioi赛制还是很需要注意时间的。
周六天梯训练赛,好几题差一俩分没拿满,在举特例方面能力非常薄弱,很多情况都会考虑不到,最后还有一点时间的时候不太想写了,以后也要注意调整状态,坚持到最后一刻。
周六晚上atcoder,只做出了ab,c题给我做的WA,RE,TLE就是没AC。
周日补题补题补题。
二、算法
1.二进制
<1>(SMU 2024 spring 天梯赛2 7-8)
前世档案 20分
写出来了但是暴力费时
题解:
输入n为问题数量,m为玩家人数即询问次数,输出每行答案代表得到哪个结论
二进制思维,敏感度
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin>>n>>m;
while(m--){
string s;
cin>>s;
int ans=1; //结论从1开始标号
for(int i=0;i<s.length();i++){
if(s[i]=='n'){ //代表这个位置的1
ans+= 1<<(n-i-1); //左移多少位后
}
}
cout<<ans<<endl;
}
return 0;
}
#include<iostream>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin>>n>>m;
int nn=1;
for(int i=0;i<n;i++){
nn=nn*2;
}
while(m--){
char bh[n];
int l=1,r=nn;
int mid=(l+r)/2;
for(int i=0;i<n;i++){
cin>>bh[i];
if(bh[i]=='y'){
r=mid;
}
else if(bh[i]=='n'){
l=mid;
}
mid=(l+r)/2;
}
cout<<r<<endl;
}
}
原暴力ac代码,题目较简单,重在思维算法。
2.STACK函数
<1>(SMU 2024 spring 天梯赛3 7-10)
列车厢调度 25分
20分的代码,最长序列的一般可行情况没过,改不了。
题解:
三节车厢,给出两行字符串仅包含26个大写字母且不重复,第一行代表原车厢,第二行代表需要的进栈顺序,用stack进出即可。
代码:
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
stack<char>s1,s2,s3;
int a[100];
int b[100];
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
string c1,c2;
cin>>c1>>c2;
int t1=0,t2=0;
int m=0;
for(int i=0;i<=60;i++){{
if(s2.size()==c2.length()){
m=i;
break;
}
}
if(c1[t1]==c2[t2]){
s2.push(c1[i]);
a[i]=1;
b[i]=2;
t2++;
t1++;
}
else {
if(s3.empty()){
s3.push(c1[i]);
a[i]=1;
b[i]=3;
t1++;
}
else if(s3.top()==c2[t2]){
s2.push(s3.top());
s3.pop();
a[i]=3;
b[i]=2;
t2++;
}
else {
s3.push(c1[i]);
a[i]=1;
b[i]=3;
t1++;
}
}
}
if(s1.size()!=0||s3.size()!=0){
cout<<"Are you kidding me?"<<endl;
}
else {
for(int i=0;i<m;i++){
cout<<a[i]<<"->"<<b[i]<<endl;
}
}
return 0;
}
3. reverse函数
引入头文件algorithm
可用于反转int和char数组,用法类似于reverse(a,a+10)
当反转字符串时,需要begin()和end()左右翻转,用法见下方代码。
<1>(SMU 2024 spring 天梯赛2 7—6)
福到了 分数十五分
解释一下当时是做出来的,但实在太暴力了我自己也受不了,就去学了一下这个函数。
题解:
题意较为简单,输入字符fh和行数n,以及一份网格,输出网格翻转后的图形,并将每个@替换为fh,如果网格翻转后与原来相同则多输出一行bu yong dao le。
一个vector数组ms储存字符串,swap上下颠倒,reverse左右颠倒,与原来相同就输出一句话和网格,否则直接输出网格。
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
char fh;
int hs;
cin>>fh>>hs;
string s;
getline(cin,s);
vector <string> ms (hs);
for(auto &s:ms){
getline(cin,s);
}
auto xs=ms;
for(int i=0;i*2<hs;i++){
swap(ms[i],ms[hs-i-1]);
}
for(int i=0;i<hs;i++){
reverse(ms[i].begin(),ms[i].end());
}
size_t t=ms[0].length();
if(ms==xs){
cout<<"bu yong dao le"<<endl;
}
for(int i=0;i<hs;i++){
for(int j=0;j<t;j++){
if(ms[i][j]==' ')cout<<' ';
else cout<<fh;
}
cout<<endl;
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int zf[102][102]={0};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
char a;
int n;
cin>>a>>n;
int t=0;
bool p=true;
char ls;
string s;
getline(cin,s);
for(int i=1;i<=n;i++){
getline(cin,s);
t=s.length();
for(int j=0;j<s.length();j++){
if(s[j]=='@'){
zf[i][j+1]=1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=t;j++){
if(zf[i][j]!=zf[n-i+1][t-j+1]){
p=false;
break;
}
}
}
if(p) {
cout<<"bu yong dao le"<<endl;
}
for(int i=n;i>=1;i--){
for(int j=t;j>=1;j--){
if(zf[i][j]==1)cout<<a;
else cout<<' ';
}
cout<<endl;
}
return 0;
}
以上是原暴力ac代码,会浪费比较多时间去写。
4. substr函数
字符截取函数
记住就行,比较常用
string h=s.substr(5); //h为从s的下标为5取到最后
string h=s.substr(5,3); //h为从s的下标为5取三位
随便举个实用例子吧
<1>(Atcoder ABC347 B)
#include <iostream>
#include <set>
using namespace std;
set<string>a;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
string s;
cin>>s;
for(int i=0;i<s.length();i++){
for(int j=i;j<s.length();j++){
string t=s.substr(i,j-i+1);
a.insert(t);
}
}
cout<<a.size()<<endl;
return 0;
}
5.BFS算法
<1>(SMU 2024 spring 天梯赛3 7-10)
题解:
输入城市个数n,道路条数m,m行输入道路信息,后k行被攻占编号,用俩个bfs构造联通域之后便利输出。
代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
vector <int> sa[5005];
int vis[5005];
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
sa[a].push_back(b);
sa[b].push_back(a);
}
for(int i=0;i<n;i++){
vis[i]=-1;
}
for(int i=0;i<n;i++){
if(vis[i]==-1){
queue<int>q;
q.push(i);
vis[i]=i;
while(q.size()){ //一个BFS深搜
int now=q.front();
q.pop();
for(auto& net :sa[now]){ //遍历now的所有邻居
if(vis[net]==-1){ //未访问过的加入队列
vis[net]=i;
q.push(net);
}
}
}
}
}
int k;
cin>>k;
int cnt=1;
queue<int>la;
for(int i=0;i<k;i++){
int a;
cin >> a;
int col = vis[a] + n + 1;
cnt = 0;
for (int j = 0; j < n; j++) {
cout<<vis[j]<<' '<<vis[a]<<endl;
if (vis[j] == vis[a] && j != a) {
vis[j] = col;
cout<<j<<endl;
}
}
vis[a] = -1; //表示已经被攻占
for(int j=0;j<n;j++){
if(vis[j]==col){ //都是一个组的
la.push(j);
vis[j]=j;
while(la.size()){ //又一个BFS深搜
int now=la.front();
la.pop();
for(auto& net :sa[now]){
if(vis[net]==-1){
vis[net]=j;
la.push(net);
}
}
}
cnt++; //表明组内被攻占城市数
}
}
if(cnt>1){
cout<<"Red Alert: City "<<a<<" is lost!"<<endl;
}
else cout<<"City "<<a<<" is lost."<<endl;
vis[a]=-1; //复原
}
if(k==n){
cout<<"Game Over."<<endl;
}
return 0;
}
6.Floyd算法
<1>(SMU 2024 spring 天梯赛3 7-9)
哈利波特的考试 分数25 分
投机取巧了,复杂度n的三次方但是数据比较小,另外djst算法实在是写不出来。
题解:
输入动物总数n和变形魔咒术m,求由选中的动物变成其它动物的最长路径最小值,并输出自己的编号。
多源最短路径问题,做的挺暴力的看代码吧。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int g[105][105];
int n,m;
void floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=(g[i][j])>(g[i][k]+g[k][j])?(g[i][k]+g[k][j]):(g[i][j]);
} //最短路径思维
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int p=0;
cin>>n>>m;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++){
if(i==j) g[i][j]=0;
else g[i][j]=1000008;
}
}
int miin=999999;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
g[a][b]=c;
g[b][a]=c;
}
floyd();
for(int i=1;i<=n;i++){
int max=-1;
for(int j=1;j<=n;j++){
if(i!=j&&g[i][j]>max)max=g[i][j];
}
if(max<miin){
miin=max;
p=i;
}
}
if(!p)cout<<0<<endl;
else
cout<<p<<" "<<miin<<endl;
return 0;
}
三、总结
有关补题的,补题最好能补到至少俩题25分题.
在条件语句 if(s2.top()==c2[t2]) 中,没有检查栈 s2 是否为空就直接调用 s2.top(),如果 s2 为空,则会导致段错误。记住这段文字,价值二十分。
除数或mod数为0会导致浮点错误,有些编译器无法提示错误。
补题的时候发现现在做的题目类型非常多样,要学会融会贯通,举一反三,也要更好地掌握各个算法,不少算法了解了但写起来并不熟练,注重补题吧。