F-Tokitsukaze and Eliminate (hard)_2024牛客寒假算法基础集训营2 (nowcoder.com)
题面:
思路:
- 贪心求最优问题
- 用两个map存储,一个mp存各个元素及其对应的个数,一个mp1存每轮遍历的元素和其个数
- 从后往前遍历,如果mp1.size()刚好等于mp.size则满足一轮遍历(在遍历中要更新mp和mp1,并用erase删除mp遍历完的元素),如此从后向前遍历一轮即可
- 最后再将余下的纯数一个个处理,所以直接加其个数即可
(当时写的时候没写出来是因为我当时没想明白题目的意思,我不知道他是怎么去消除那些石头,我看了官方题解才明白题目的意思!!!说的到底还是我的思路出现了问题,还是需要多加练习练习去理解题目要求的)
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+10;
int a[N];
void solve()
{
int n;
cin>>n;
map<int,int> mp,mp1;
int ans=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
mp[a[i]]++;
}
int s=mp.size();
for(int i=n;i>=1;i--)
{
mp[a[i]]--;
mp1[a[i]]++;
if(mp[a[i]]==0) mp.erase(a[i]);
if(mp1.size()==s)
{
ans++;
s=mp.size();
mp1.clear();
}
}
cout << ans <<endl;
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T=1;
cin>>T;
while(T--) solve();
}
7-2 地下迷宫探索 - SMU 2024 winter round 3(补题) (pintia.cn)
题面:
题解:理解题意后发现就是一个dfs,由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。
(我当时没写出来主要是卡在前面的一些题就没有看这题,
AC代码:
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string>
using namespace std;
int v[1005];
int b[1005][1005];
int n,m,s;
void dfs(int s)
{
if(v[s]) return;
v[s]=1;
for(int i=1;i<=n;i++)
{
if(b[s][i]&&!v[i])
{
printf(" %d",i);
dfs(i);
printf(" %d",s);
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
memset(v,0,sizeof(v));
memset(b,0,sizeof(b));
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
b[x][y]=1;
b[y][x]=1;
}
printf("%d",s);
dfs(s);
for(int i=1;i<=n;i++)
{
if(v[i]==0)
{
printf(" 0");
break;
}
}
printf("\n");
return 0;
}
D-chino's bubble sort and maximum subarray sum(easy version)_2024牛客寒假算法基础集训营3 (nowcoder.com)
题面:
思路:给出一段长度为N的数组,进行K次相邻元素的交换操作,求出最大子段和,数据给的比较小,且K=0或K=1,用前缀和处理然后暴力即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
const ll N=1e6+10;
ll n,m,k,t,sum,ans,flag;
ll cnt[N];
ll a[N];
string s,s1;
void slove(){
cin>>n>>k;
for(ll i=1;i<=n;i++) cin>>a[i];
if(k==1){
ans=-1e16;//a有<0的情况,取一个比较小的负值
for(ll i=1;i<n;i++){
swap(a[i],a[i+1]);//进行交换
cnt[0]=0;//初始化
for(ll i=1;i<=n;i++) cnt[i]=cnt[i-1]+a[i];//前缀和
for(ll i=0;i<=n;i++){
for(ll j=i+1;j<=n;j++)
ans=max(ans,cnt[j]-cnt[i]);//cnt[j]-cnt[i]即i到j的子段和
}
swap(a[i],a[i+1]);//换回来,避免对后续产生影响
}
cout<<ans<<'\n';
}
else if(k==0){
cnt[0]=0;
for(ll i=1;i<=n;i++) cnt[i]=cnt[i-1]+a[i];
for(ll i=0;i<=n;i++){
for(ll j=i+1;j<=n;j++)
ans=max(ans,cnt[j]-cnt[i]);
}
cout<<ans<<'\n';
}
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll _ = 1;
//cin >> _;
while (_--) slove();
return 0;
}
B-智乃的数字手串_2024牛客寒假算法基础集训营3 (nowcoder.com)
思路:(博弈论)
n=1时,必然是qcjj赢;(必胜态)
n=2时,无论是奇数还是偶数,qcjj必输;(必败态)
n=3时,qcjj可以取出一个数将其转换为n=2时的状态,这对zn来说必输;(必胜态)
n=4时,同样可以转换到n=3时的转态
总结得到n是奇数时,qcjj赢;n是偶数时,zn赢。
AC代码:
#include <bits/stdc++.h>
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t,n;
cin>>t;
while(t--)
{
cin>>n;
int a[30];
for(int i=1;i<=n;i++)
cin>>a[i];
if(n%2==0)cout<<"zn"<<endl;
else cout<<"qcjj"<<endl;
}
return 0;
}
7-11 敲笨钟 - SMU 2024 winter round 3(补题) (pintia.cn)
题面:
思路:按照题目的意思即可,我当时没写就是没想到使用string类的各种函数以及如何处理输入,
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n;
char ch;
string s;
int main()
{
cin>>n;
while((ch=getchar())!='\n')continue;
while(n--)
{
getline(cin,s);
if(s.find("ong,")!=string::npos&&s.find("ong.")!=string::npos)
{
for(int k=1;k<=3;k++)
{
int t=s.rfind(" ");
for(int i=t;s[i]!='\0';i++)s.erase(i--);
}
cout<<s<<" qiao ben zhong."<<endl;
}
else cout<<"Skipped"<<endl;
}
return 0;
}
(这周是有点偷懒了,补的题就没有那么多,现在年过完了,下周得好好收收心干我该干的事了)