博客主页:PH_modest的博客主页
当前专栏:每日一题
其他专栏:
每日反刍
C++跬步积累
C语言跬步积累
座右铭:广积粮,缓称王!
题目大意:你的朋友有一个长度为n的数组,该数组中的数字是由1~n组成,不会有重复的数字,他计算了前缀和并将其传递给你,但再传递过程中丢失了一个数(前缀和中的一个数),你需要根据缺失的前缀和数组判断是否有与其匹配的置换。
例如,原始置换为[ 1、5、2、4、3]。其前缀和数组 [ 1、6、8、12、15]。丢失一个元素,可以得到数组[ 6、8、12、15]或[ 1、6、8、15]。
题目链接:D. Prefix Permutation Sums (Codeforces Round 888 (Div. 3))
#include
#include
#define int long long
using namespace std;
int s[200020];
map<int,int>mp;//存放前缀和之间的差值
void solve()
{
int n;
mp.clear();//初始化
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>s[i];
}
mp[s[0]]++;//将第一个前缀和数字放入
for(int i=1;i<n-1;i++)
{
mp[s[i]-s[i-1]]++;//放入两个相邻前缀和的差值
}
int sums=0;//记录原数组中少的数字之和是多少
int flag=0;//原数组少了几个数字
for(int i=1;i<=n;i++)
{
if(mp[i]==0)//少了的数字
{
sums+=i;
flag++;
}
if(mp[i]>0)//如果这个数字没有少,就需要把之前的标记撤销掉,如果不撤销会出问题,想想为什么
{
mp[i]--;
}
}
if(flag==1)//如果flag为1,说明丢失的是最后一个数,无论怎么样都符合条件
{
cout<<"YES"<<"\n";
return;
}
if(flag>2)//如果大约2直接输出no
{
cout<<"NO"<<"\n";
return;
}
if(flag==2)//等于2说明丢失的是前面的数字
{
if(mp[sums]==0)//丢失的数字之和没有被标记
{
cout<<"NO"<<"\n";
return;
}
else
{
cout<<"YES"<<"\n";
return;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
每日一题系列旨在养成刷题的习惯,所以对代码的解释并不会特别详细,但足够引导大家写出来,选的题目都不会特别难,但也不是特别简单,比较考验大家的基础和应用能力,我希望能够将这个系列一直写下去,也希望大家能够和我一起坚持每天写代码。
之后每个星期都会不定期更新codeforces和atcoder上的题目,想要学习算法的友友们千万别错过了,有什么疑问欢迎大家在评论区留言!
在这里送大家一句话:广积粮,缓称王!