3.31~4.6
牛客月赛113
A

签到
#include <bits/stdc++.h>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int sum = 1;
string s;
cin >> s;
for(char i : s){
if(i == '-') sum -= 1;
else sum *= 2;
}
cout << (sum >= 2025 ? "YES\n" : "NO\n");
return 0;
}
B

统计相邻相同字符即可
#include <bits/stdc++.h>
using namespace std;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,times=0;
string s;
cin >> n >> s;
for(int i=1;i<n;i++){
if(s[i] == s[i-1])
times++;
}
cout << (times<=1 ? "YES\n" : "NO\n");
return 0;
}
C

很简单的题,就是对数组进行几个判定:
1.如果输入数组里出现了逆序的情况,NO
2.如果所有输入数组里有相同数的情况,NO
3.将所有数组合并,如果有逆序的情况,NO
否则,YES
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+1;
vector <int> vec;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int q,pd=1,sum=0;
cin >> q;
while(q--){
int k;
cin >> k;
sum += k;
int arr[maxn];
arr[0] = 0;
for(int i=1;i<=k;i++){
cin >> arr[i];
if(arr[i] < arr[i-1])
pd = 0;
vec.push_back(arr[i]);
}
}
sort(vec.begin(),vec.end());
for(int i=1;i<sum;i++){
if(vec[i]-vec[i-1] != 1){
pd = 0;
break;
}
}
cout << (pd ? "YES\n" : "NO\n");
return 0;
}
D

思维题,需要惊人的注意力才能注意到:
对数组升序排序后,在每个"断点"(a[i]-a[i-1]!=1)处进行处理,sum累加上a[i]-a[-1]-1,因为每个断点所隔开的区间里,区间里的数都是同时变为0的
有特判:输入数组为相同数,0;输入数组没有0,-1
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e5+1;
int a[maxn];
signed main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,pd=1;
cin >> n;
for(int i=0;i<n;i++){
cin >> a[i];
if(i && a[i]!=a[i-1])
pd = 0;
}
sort(a,a+n);
if(pd){
cout << "0\n";
return 0;
}
if(a[0]){
cout << "-1\n";
return 0;
}
int sum = 0;
for(int i=1;i<n;i++){
if(a[i]-a[i-1] != 1 && a[i]!=a[i-1]){
sum += a[i]-a[i-1]-1;
}
}
cout << ++sum << '\n';
return 0;
}
E

区间DP+预处理
有难度的,揣摩了官方题解才过。简而言之就是通过预处理左右合法区间,然后dp每个大小区间,逐步推出最大的区间数k
预处理:
pre[]:左侧与ai不互质的最近的j
nex[]:右侧与ai不互质的最近的i
状态转移:
<font style="color:rgb(0, 0, 0);">dp[i] = max(dp[i], dp[j-1] + 1)</font>
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e3+5;
int n,a[N],pre[N],nex[N],dp[N];
void solve(){
for(int i=1;i <= n;i++){
for(int j=1;j < i;j++){
if(__gcd(a[i],a[j]) != 1){
pre[i] = max(pre[i] , j);
nex[j] = min(nex[j] , i);
}
}
}
for(int i=1;i <= n;i++){
int t = 1e9;
for(int j=i;j >= 1;j--){
if(nex[j] > i)
t = min(t,pre[j]);
else if(t >= j && dp[j-1] != -1)
dp[i] = max(dp[i], dp[j-1]+1);
}
}
cout << dp[n] << '\n';
}
signed main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
memset(dp,-1,sizeof(dp));
dp[0] = 0;
memset(nex,0x3f,sizeof(nex));
for(int i=1;i <= n;i++)
cin >> a[i];
solve();
return 0;
}
洛谷P1004

这道dp还是有难度的,洛谷题名绿绿的
容易想到dp和dfs。dfs剪枝可以过;如果dp两遍,每遍都贪心找局部最优,这样可能会陷入局部最优解从而出错。
因此比较无脑的正解是四维dp
同时考虑如何第一遍到点(i,j)以及第二遍到点(k,l),共四种情况:
- 路径 1 从 (i-1, j) 来,路径 2 从 (k-1, l) 来,前一状态为
<font style="color:rgb(0, 0, 0);">dp[i-1][j][k-1][l]</font> - 路径 1 从 (i-1, j) 来,路径 2 从 (k, l-1) 来,前一状态为
<font style="color:rgb(0, 0, 0);">dp[i-1][j][k][l-1]</font> - 路径 1 从 (i, j-1) 来,路径 2 从 (k-1, l) 来,前一状态为
<font style="color:rgb(0, 0, 0);">dp[i][j-1][k-1][l]</font> - 路径 1 从 (i, j-1) 来,路径 2 从 (k, l-1) 来,前一状态为
<font style="color:rgb(0, 0, 0);">dp[i][j-1][k][l-1]</font>
取最大的,所以状态转移方程为:
dp[i][j][k][l] = max(
max(dp[i-1][j][k-1][l], dp[i-1][j][k][l-1]),
max(dp[i][j-1][k-1][l], dp[i][j-1][k][l-1])
) + room[i][j] + room[k][l];
注意,当两遍的点重复,即i==k,j==l时,这个点的数被重复算了,要减去一遍的它if(i==k && j==l) dp[i][j][k][l] -= room[i][j];
code:
#include <bits/stdc++.h>
using namespace std;
int dp[10][10][10][10]={0},room[10][10]={0};
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,x,y,i;
cin >> n;
while(114514){
cin >> x >> y >> i;
if(!x) break;
room[x][y] = i;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
for(int l=1;l<=n;l++){
dp[i][j][k][l] = max(max(dp[i-1][j][k-1][l],dp[i-1][j][k][l-1]),max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1])) + room[i][j] + room[k][l];
if(i==k && j==l) dp[i][j][k][l] -= room[i][j];
}
cout << dp[n][n][n][n] << '\n';
return 0;
}
成理蓝桥试炼赛
D

map模拟即可
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6+1;
int a[maxn],score;
map <int,int> ma;
signed main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,m;
cin >> n >> m;
for(int i=0;i<n;i++)
cin >> a[i];
for(int i=0;i<n;i++){
cin >> score;
ma[a[i]] = score;
}
int sum = 0;
for(int i=0;i<m;i++){
int inp;
cin >> inp;
sum += ma[inp];
}
cout << sum << '\n';
return 0;
}
剩下的题下周补了,这周事情实在多......

浙公网安备 33010602011771号