训练情况
赛后反思
C题犯蠢了,手玩几下就能猜出来的结论,结果自己想复杂了,以为是二分,D题又复现传智杯二分爆long long了,又没注意到,E题BFS搜索没记忆化MLE了
D题
传智杯二分爆long long重现,怒开__int128发现还是爆,只能边加边特判了,我们对于这题显然能观察到二分单调性,直接二分答案,判断最后利润是否 \(\ge m\)。
点击查看代码
#include <bits/stdc++.h>
#define int __int128
#define endl '\n'using namespace std;const int N = 1e6 + 3;int n,m;
int a[N];inline int read(){int s = 0; char c = getchar();while(!isdigit(c)) c = getchar();while(isdigit(c)) s = (s << 1) + (s << 3) + (c ^ 48),c = getchar();return s;
}void print(int x){if(x>9) print(x/10);putchar(x%10+48);
}bool pd(int x){int ans = 0;int now = x;for(int i = 2;i<=n;i++){if(a[i] > a[i-1]){int gx = (now/a[i-1]) * (a[i] - a[i-1]);ans += gx;if(ans >= m) return true;now += gx;}}return ans >= m;
}void solve(){n = read(); m = read();for(int i = 1;i<=n;i++) a[i] = read();int l = 0,r = 1e18+1,m;while(l<r){m = l + r >> 1;if(pd(m)) r = m;else l = m + 1;}if(l == 1e18+1) cout<<"-1"<<endl;else print(l),puts("");
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}
E题
BFS模板题,提前维护相同数字的位置,入队操作加入左右两边和相同的数字,记录到达终点的步数即可,这题需要记忆化一下,记录当前位置的最小步数,遇到记录过的就跳过,不然会重复入队 MLE。
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define pii pair<int,int>
#define endl '\n'using namespace std;const int N = 1e6 + 3;int n;
int a[N];
vector<int> v[N];
vector<int> d(N);void bfs(int st){queue<pii> q;q.push({st,0});while(q.size()){int x = q.front().first;int step = q.front().second;q.pop();if(d[x]) continue;d[x] = step;if(x == n){cout<<step<<endl;exit(0);}if(x==1) q.push({x+1,step+1});else q.push({x-1,step+1}),q.push({x+1,step+1});for(auto i:v[a[x]]){if(i == x) continue;q.push({i,step+1});}}
}void solve(){cin>>n;for(int i = 1;i<=n;i++) cin>>a[i],v[a[i]].emplace_back(i);bfs(1);
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}
K题
签到题,直接记录连续的天数,累加答案即可
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'using namespace std;void solve(){int ans = 0;int n; cin>>n;int now = 0;for(int i = 1;i<=n;i++){int x; cin>>x;if(x == 1) now++;else now = 0;ans+=now;}cout<<ans<<endl;
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}
L题
签到题加强版,我们直接维护映射记录对应人的连续天数,累加答案即可,还需要额外开一个变量记录谁当天没签过到,遇到隔天就连续天数全部清零,这题有个坑点,有人会一天内连续签到,注意特判一下即可
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'using namespace std;map<string,int> ans;
map<string,int> now;
map<string,bool> vis;void solve(){int q; cin>>q;while(q--){int opt; cin>>opt;if(opt == 1){string s; cin>>s;if(vis[s]) continue;now[s]++;vis[s]=1;ans[s] += now[s];} else if(opt == 2){string s; cin>>s;cout<<ans[s]<<endl;} else if(opt == 3){for(auto i:now){if(!vis[i.first]) now[i.first] = 0;}vis.clear();}}
}signed main(){// int T; cin>>T; while(T--)solve();return 0;
}