Codeforces Round 987 (Div. 2)
Codeforces Round 987 (Div. 2) 总结
A
常见的套路,将一个序列变为不下降序列所需要改变的值的最小数量,考虑最大能保留多少个,显然是求最长上升子序列,而这题给出的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=55;
int n;
int a[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0,len=0;
for(int i=1;i<=n;i++)
{
if(a[i]!=a[i-1]) ans=max(ans,len),len=1;
else len++;
}
ans=max(ans,len);
cout<<n-ans<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
B
考虑每个数
首先能交换的值只有
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int st=1;
for(int i=1;i<=n;i++)
{
if(a[i]<i&&!(i-a[i]==1&&a[a[i]]==a[i]+1)) st=0;
else if(a[i]>i&&!(a[i]-i==1&&a[a[i]]==a[i]-1)) st=0;
}
if(st) cout<<"Yes\n";
else cout<<"No\n";
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
C
构造题,思路还是比较清晰的。
首先不难想到
再考虑奇数,由于任意两个相同的馅料之间的距离都要是完全平方数,考虑三个相同的,位置为
考虑最小的勾股数
后面就按偶数的接下去就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
void solve()
{
cin>>n;
if(n%2==0)
{
int cnt=1;
for(int i=1;i<=n;i+=2) a[i]=a[i+1]=++cnt;
}
else
{
if(n>=27)
{
a[1]=a[10]=a[26]=1;
int cnt=1;
for(int i=2;i<=8;i+=2) a[i]=a[i+1]=++cnt;
for(int i=11;i<=21;i+=2) a[i]=a[i+1]=++cnt;
a[23]=a[27]=++cnt;
a[24]=a[25]=++cnt;
for(int i=28;i<=n;i+=2) a[i]=a[i+1]=++cnt;
}
else
{
cout<<-1<<'\n';
return ;
}
}
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
D
赛时的清奇想法。
首先发现能跳跃的两个位置是逆序对,因此考虑用并查集维护,并记录集合内最大值与最小值。
再考虑这样一种做法,先遍历一遍数组,目前遇到的最大值为
- 若
更新 和 。 - 若
那么就合并 和 。
以最后一组样例为例:
用
然后考虑合并不同集合,从后往前,如果出现两个不同集合
那有没有可能出现不是相邻的集合合并呢?答案是否定的,考虑
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n;
int a[N],ans[N];
int fa[N],mi[N],mx[N];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
x=fa[x],y=fa[y];
fa[y]=x;
mi[x]=min(mi[x],mi[y]);
mx[x]=max(mx[x],mx[y]);
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
fa[i]=i;
mi[i]=mx[i]=a[i];
}
int x=a[1],id=1;
for(int i=2;i<=n;i++)
{
if(a[i]<x) merge(id,i);
else x=a[i],id=i;
}
for(int i=n-1;i>=1;i--)
if(find(i)!=find(i+1)&&mi[find(i+1)]<mx[find(i)])
merge(i,i+1);
for(int i=1;i<=n;i++) cout<<mx[find(i)]<<' ';
cout<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
分类:
codeforces总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」