A
思路 简单的if判断是否为真
代码如下
#include<bits/stdc++.h>
using namespace std;
int main(){
int l=0,r=0;
cin>>l>>r;
if(l==1&&r==0){
cout<<"Yes"<<endl;
}
else if(l==0&&r==1){
cout<<"No"<<endl;
}
else {
cout<<"Invalid"<<endl;
}
return 0;
}
B题
简单的一个从数列中求出大的那个数再变成数列中大的那个数
代码如下
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
int a[105][105]={0};
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
int l=1;
for(int i=1;i<=n;i++){
int l1=max(l,i);
int r1=min(l,i);
l=a[l1][r1];
}
cout<<l<<endl;
return 0;
}
C题
比较两个字符串不同的地方 再按着顺序从上到下输出每一步更改的地方|
代码如下
因为按字典序顺序输出 所以要如果第一行前面的ASCII码大于大二行要先改,如果小于第二行的渝要从后往前改小于的 这样才能保证顺序是从小到大的
代码如下
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
string t;
cin>>t;
int cnt=0;
int len=s.length();
for(int i=0;i<len;i++){
if(s[i]!=t[i]){
cnt++;
}
}
cout<<cnt<<endl;
for(int i=0;i<len;i++){
if(s[i]>t[i]){
s[i]=t[i];
cout<<s<<endl;
}
}
for(int i=len-1;i>=0;i--){
if(s[i]<t[i]){
s[i]=t[i];
cout<<s<<endl;
}
}
return 0;
}
D题
思路 由于数据量大再加上本体是查询之类的操作 可以考虑用set来做
还有来找边界问题 可以用lower_bound以及对其--来求上下界左右界
代码如下
if (g1[R].count(C)) {
erase(R, C);
continue;
}
// up
{
auto it = g2[C].lower_bound(R);
if (it != begin(g2[C])) erase(*prev(it), C);
}
// down
{
auto it = g2[C].lower_bound(R);
if (it != end(g2[C])) erase(*it, C);
}
// left
{
auto it = g1[R].lower_bound(C);
if (it != begin(g1[R])) erase(R, *prev(it));
}
// right
{
auto it = g1[R].lower_bound(C);
if (it != end(g1[R])) erase(R, *it);
}
}
E题
思路 求数组序列中分成若干个子序列求和不为K的总次数 求和不为K以及每一步都和上一个序列有关可以想到dp,由于要求序列之和的问题 可以使用前缀和 在这么多的序列中由于等于K的次数很少 而不等于K的很多 可以开一个map来存前缀和为K,然后求出dp的前缀和减去当以i结尾时的和是k的次数就可以更新dp[i]了
代码如下
for(int i = 1; i <= n; i++){
cin >> a[i];
a[i] += a[i - 1];
}
vector<ll> dp(n + 1 , 0) , sum(n + 1 , 0);
map<ll,ll> no;
dp[0] = sum[0] = 1;
no[0] = 1;
for(int i = 1; i <= n; i++){
dp[i] = (sum[i - 1] - no[a[i] - k] + mod) % mod;;
dp[i] %= mod;
sum[i] = sum[i - 1] + dp[i];
sum[i] %= mod;
no[a[i]] += dp[i];
no[a[i]] %= mod;
}
cout << dp[n] << endl;
}
F题
思路
看到最小值求最大首先想到的就是二分,首先想到二分出最大值,这个题由于是环,所以需要化成链即a[i+n]=a[i],一个链上有很多断点,如果全部列举跑的话是会超时的,所以需要考虑到倍增思路,即跑2的次方,如果一个位置 i+n 跳 k 次后仍然位于 [i+1,i+n] 这个区间上,那么 i 的答案就大于 mid
int l = 1, r = 0;
while (l <= 2 * n)
{
if (r < l)
r = l;
while (r + 1 <= 2 * n && s[r]-s[l-1] < mid)
r++;
if ( s[r]-s[l-1] >= mid)
nx[0][l] = r + 1;
l++;
}
for (int j = 1; j < 20; j++)
for (int i = 1; i <= 2 * n; i++)
nx[j][i] = nx[j - 1][i] == inf ? inf : nx[j - 1][nx[j - 1][i]];
int ret = 0;
for (int i = 1; i <= n; i++)
{
int cnt = 0;
int q = i;
for (int j = 19; j >= 0; j--)
{
if (nx[j][q] <= i + n)
q= nx[j][q], cnt = 1 << j;
}
if (cnt >= k)
ret++;
}
return ret;
}