A. Submission Bait
当某个数字出现次数为奇数时,Alice就可通过选取该数取得胜利
void solve(){
cin>>n;
map<int,int> mp;
for(int i=0;i<n;i++) cin>>a[i],mp[a[i]]++;
for(int i=0;i<n;i++){
if(mp[a[i]]%2){
cout<<"YES"<<endl;return;
}
}cout<<"NO"<<endl;
}
B. Array Craft
构造题,前缀和最大即在x位置后不能出现连续的一段1,且x+1位置必须为-1,后缀和最大即y位置前不能出现连续的一段1,且y-1位置为-1,x+1位置后和y-1位置前交替1和-1,绝对值和均为0或1,x和y间均为1,这样构造就可在x处取最大前缀和,而且索引是最小的,y处取最大后缀和,而且索引是最大的
void solve(){
cin>>n>>x>>y;
for(int i=1;i<y;i++){
if((y-1)%2){
if(i%2) cout<<-1<<" ";
else cout<<1<<" ";
}
else{
if(i%2) cout<<1<<" ";
else cout<<-1<<" ";
}
}
for(int i=y;i<=x;i++) cout<<1<<" ";
for(int i=x+1;i<=n;i++){
if((x+1)%2){
if(i%2) cout<<-1<<" ";
else cout<<1<<" ";
}
else{
if(i%2) cout<<1<<" ";
else cout<<-1<<" ";
}
}cout<<endl;
}
C. Mad MAD Sum
看了大佬发现的性质,第一轮整理后,数列会变成单调不减的数列,第二轮整理后,除了最大数可能为1,数列中剩下的元素的数量必然大于2,从第三轮开始,就是每次数列右移一位,所以就可以根据 ai*(n-i) 来算对答案的贡献了,
void solve(){
cin>>n;
ll sum=0,maxs=0;
map<int,int> mp;
for(int i=0;i<n;i++) cin>>a[i],sum+=a[i];
for(int i=0;i<n;i++){
mp[a[i]]++;
if(mp[a[i]]>=2&&maxs<a[i]) maxs=a[i];
a[i]=maxs;
sum+=a[i];
}mp.clear();maxs=0;
//for(int i=0;i<n;i++) cout<<a[i]<<" ";cout<<endl;
for(int i=0;i<n;i++){
mp[a[i]]++;
if(mp[a[i]]>=2&&maxs<a[i]) maxs=a[i];
a[i]=maxs;
}mp.clear();
//for(int i=0;i<n;i++) cout<<a[i]<<" ";cout<<endl;
for(int i=0;i<n;i++){
sum+=a[i]*(n-i);
//cout<<i<<" "<<a[i]<<" "<<sum<<endl;
}cout<<sum<<endl;
}
D. Grid Puzzle
又是看大佬的,用tag1数组表示第一二个块,tag2数组表示第三四块,小于等于2的行均用操作一,这样是最优的,因为可以涉及到下一行的两个,小于等于4的行,如果有块被上一行的操作消除,就考虑消剩下的块,如果大于4的行,直接用操作二
void solve(){
int ans=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],tag1[i]=tag2[i]=0;
for(int i=1;i<=n;i++){
if(!a[i]) continue;
if(tag1[i]&&a[i]<=2) continue;
if(tag1[i]&&tag2[i]&&a[i]<=4) continue;
if(a[i]<=2) tag1[i]=tag1[i+1]=1;
else if(a[i]<=4){
if(tag1[i]) tag2[i]=tag2[i+1]=1;
else if(tag2[i]) tag1[i]=tag1[i+1]=1;
}
ans++;
}cout<<ans<<endl;
}