简单点评一下同学们现在的问题:
1 简单思维讨论类型的题目,准确率还不够,每个题目都要经过全方面的考虑再去设计算法程序 不然就会像A题一样 有同学能错七八次 才能写对
程序写完以后自己多测测样例数据,
自己造数据去测
2 算法类型的题目不知道如何思考,这个需要慢慢积累
3 学习要踏实,勤奋,初赛训练的时候不要用编译器做题。综合来看同学们现在需要大量的积累,更加精细化的分类讨论能力,全方位的思考问题的耐心。心中有模拟赛,自然都是模拟赛
A题题解
很明显的一个分类讨论题目
如果字符串中存在相邻且相等的字符位置,那么记录下来 为pos
先输出1--pos 然后输出插入的字符 注意要跟pos pos+1位置的字符不一样,然后输出pos+1~ 末尾的字符 这样子就构造好了
如果不存在这样子的位置,那更好办了,直接输出字符串在末尾补一个不一样的字符即可
cpp
#include<bits/stdc++.h>
using namespace std;
char A[1010];
int main(){
int a;
cin>>a;
char b;
int ib;
int ok=0;
for(int i=1;i<=a;i++){
cin>>A+1;
int len = strlen(A+1);
for(int j=1;j<=len;j++){
if(A[j-1]==A[j]){
ib=j;
if(A[j]!='a'){
b='a';
ok=1;
}
else{
b='b';
ok=1;
}
}
}
int g=0;
if(ok==0){
for(int j=1;j<=len;j++){
cout<<A[j];
if(j==len){
if(A[j]=='a'){
cout<<'b';
}
else{
cout<<'a';
}
}
}
}
else{
for(int j=1;j<=len;j++){
if(j==ib){
cout<<b;
}
cout<<A[j];
}
}
ok=0;
cout<<endl;
}
return 0;
}
B题题解
首先题目意思要读懂
给定一个2*n的矩阵,里面由两种方块组成:堵塞方块和自由方块,自由方块有且只会形成一个联通块(这个条件很重要),求符合条件的自由方块个数(把这个自由方块变成堵塞方块后恰好能把一个联通块割成3个联通块)
本题只需要特判即可
cpp
#include<bits/stdc++.h>
using namespace std;
void sol(){
int n;cin>>n;
char a[3][n+10];
for(int i=1;i<=2;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
int cnt=0;
for(int i=1;i<=n-2;i++){
if(a[1][i]=='x'&&a[1][i+1]=='.'&&a[1][i+2]=='x'&&a[2][i]=='.'&&a[2][i+1]=='.'&&a[2][i+2]=='.')cnt++;
if(a[2][i]=='x'&&a[2][i+1]=='.'&&a[2][i+2]=='x'&&a[1][i]=='.'&&a[1][i+1]=='.'&&a[1][i+2]=='.')cnt++;
}
cout<<cnt<<endl;
}
int main(){
int t;cin>>t;
while(t--)sol();
return 0;
}
C题题解
给定一个由'(',')'和''三种字符组成的字符串,''出现在所有的奇数位,现在需要我们在'_'中填入'('或')',使得每个括号一定能够配对(保证一定存在这样的字符串),使得字符串的分数最大(每个括号左右下标差的累加值)
看到括号,就想到栈的使用,这道题的解法多样
枚举原字符串,一共有三种字符,分别进行操作
cpp
#include <iostream>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
typedef pair<char,LL> PII;//开long long,求求你了,记得开long long
const LL N=2e5+10;
const LL INF=1e18;
const double small=1e-16;
//千万不要用puts()和gets(),求求你了
char s[N];
void solve()
{
LL n;
cin>>n;
stack<PII> q;
for(int i=1;i<=n;i++)cin>>s[i];
LL res=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='_')//碰到'_'
{
if(q.size()&&(q.top().first=='('))//如果栈顶为左括号,优先满足
{
res+=(i-q.top().second);//配对成功
q.pop();
}
else//否则入栈等待右括号
{
q.push({'_',i});
}
}
else if(s[i]=='(')//碰到'('
{
q.push({'(',i});//直接入栈,等右边的'_'
}
else if(s[i]==')')//碰到')'
{
//if(q.size())cout<<q.top().first<<endl;
if(q.size()&&(q.top().first=='('||q.top().first=='_'))'('和'_'都可以配对
{
res+=(i-q.top().second);//配对成功
q.pop();
}
}
}
//cout<<q.size()<<endl;//这里看到栈到后面总是空的,不用再处理了
cout<<res<<endl;
}
int main()
{
int t=1;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
D 题题解
因为硬币会下落,所以说一开始硬币处于Y轴-2及以下都是收集不到的
cpp
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int n;
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
while(n--){
int x,y;
cin>>x>>y;
if(y<-1)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
E题
构造一个最短的字符串满足存在子串a以及子序列b
最坏情况是 a + b,然后,考虑 a 是一定要整段出现在答案中,所以只需要枚举从 b 的第几个字符开始匹配即可,如果有 tmp 个字符匹配,答案就是 a.size() + b.size() - tmp
注意 b 中所有字母都要按顺序出现在 a 里,所以,一旦 b 中有一个字符不能和 a 匹配,之后的所有字符都不能和 a 匹配了,直接break,就不能再往下计算了
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;
const int N = 1e5 + 10;
const int maxn = 1e6 + 10;
const int mod = 998244353;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
string a, b;
cin >> a >> b;
int ans = a.size() + b.size();
for (int k = 0; k < b.size(); k ++ )
{
int tmp = 0;
int lst = -1;
for (int i = k; i < b.size(); i ++ )
{
bool flag = false;
for (int j = lst + 1; j < a.size(); j ++ )
{
if (b[i] == a[j])
{
flag = true;
lst = j;
tmp ++ ;
break;
}
}
if (!flag) break;
}
ans = min(ans, (i64)(a.size() + b.size() - tmp));
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}
F题题解
贪心的使两个电影的评分尽可能的高且相近
1.若第i个人对两个评分不一样,取高的评分即可。
2.反之则考虑:
(1) 若ai=bi=0,则选择哪个电影都一样,所以不考虑
(2)若ai=1,则第i个人把评分给当前分低的
(3)若ai=-1,则第i个人把评分给当前分高的
cpp
#include<bits/stdc++.h>
using namespace std;
const int N =2e5+10;
int a1,b1;
int t,n,res;
void solve()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
while(t--)
{
cin>>n;
a1=b1=0;
vector<int> a(n+1),b(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
cin>>b[i];
if(b[i]>a[i]) b1+=b[i];
if(b[i]<a[i]) a1+=a[i];
}
for(int i=1;i<=n;i++)
{
if(a[i]==b[i])
{
if(a[i]*(a1-b1)>0) b1+=b[i];
else a1+=a[i];
}
}
cout<<min(a1,b1)<<endl;
}
}
int main()
{
solve();
return 0;
}
G题题解
这算是最难的一个 ,本套题里面
难度分1900
可以发现最好的策略,一定是先利用锻造并融化后损失最小的来获取经验。这个贪心是可以证明的。那我们发现a的范围是1e6,那么如果C大于最大的ai,那我们可以选择一个最小损失的方案一直执行让他小于最大的ai,小于ai后,这个数据范围可以发现,我们可以利用dp来得到1e6范围的所有答案,那么这道题就完成了
cpp
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N =1e6+10;
int n,m;
void solve()
{
vector<int> a(N),b(N);
vector<int> d(1e6+10,1e7),dp(1e6+10);
cin>>n>>m;
int s=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s=max(s,a[i]);
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
d[a[i]]=min(d[a[i]],a[i]-b[i]);
}
for(int i=1;i<=1e6;i++) d[i]=min(d[i],d[i-1]);
for(int i=1;i<=1e6;i++)
if(i-d[i]>=0) dp[i]=max(dp[i],dp[i-d[i]]+1);
LL res=0;
for(int i=1;i<=m;i++)
{
int c;
cin>>c;
if(c>s)
{
int r=(c-s)/d[s]+1;
c-=r*d[s];
res+=r;
}
res+=dp[c];
}
cout<<res*2<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
H题题解
我们考虑贪心,先把所有子树能给出的颜色的最小值记录下来,记为maxval。如果当前根结点的值比maxval大,那么取maxval(因为根节点无法影响叶子结点),否则的话,根节点和maxval取平均,通过子树把当前根的贡献增大。
难度分1500 中规中矩的题目
cpp
#include <bits/stdc++.h>
const int maxn = 3e5 + 10;
using namespace std;
int n, a[maxn], tmp[maxn];
vector<int> e[maxn];
void dfs(int u, int fa) {
int maxval = 0, flag = -1;
for (auto to: e[u])
if (to != fa) {
dfs(to, u);
if (flag == -1) {
flag = 1;
maxval = tmp[to];
} else {
maxval = min(tmp[to], maxval);
}
}
if (flag == -1) {
tmp[u] = a[u];
return;
}
if (u == 1) {
tmp[u] = a[1] + maxval;
return;
}
if (a[u] >= maxval)
tmp[u] = maxval;
else
tmp[u] = (a[u] + maxval) / 2;
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i], e[i].clear();
for (int i = 2; i <= n; i++) {
int x;
cin >> x;
e[i].push_back(x);
e[x].push_back(i);
}
dfs(1, 0);
cout << tmp[1] << endl;
}
return 0;
}