A. Sign Flipping
题目大意:
给你一个n大小的数组(n一定为奇数),现在你可以改变其中元素的符号(+/-)
在操作后,使得有至少一半的ai <= ai+1,至少有一半ai >= ai+1,现在让你构造出这个数组
思路:
1、直接正负正负(或者负正负正)的一直下去,由于n为奇数,那么肯定就满足条件
2、直接在全取绝对值,然后正负正负(或者负正负正)。
代码:
#include<stdio.h>
#include<iostream>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n, a[109]={0};
cin>>n;
for(int i=0; i<n; i++){
cin>>a[i];
if(i&1 && a[i]<0)
a[i]=a[i]*-1;
else if(!(i&1) && a[i]>0)
a[i]=a[i]*-1;
}
for(int i=0; i<n; i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
return 0;
}
B. Neighbor Grid
题目大意:
一个二维数组中任意位置的元素k周围(上下左右)有k个相邻的不为0的数的个数。
对二维数组的元素加一,能否构造出这样的二维数组。
思路:
贪心,直接将每个位置的值开到最大,例如对于4x4的矩阵:
所以只需要判断相应的位置能否通过加一的操作达到相应位置的最大值。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
int n, m, mp[309][309], flag = 0;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> mp[i][j];
if (mp[i][j] > 4)
flag = 1;
if (((i == 0 && j == 0) || (i == 0 && j == m - 1) || (i == n - 1 && j == 0) || (i == n - 1 && j == m - 1)) && mp[i][j] > 2)
flag = 1;
else if (((i == 0 || j == 0 || i == n - 1 || j == m - 1)) && mp[i][j] > 3)
flag = 1;
}
}
if (flag)
{
cout << "NO" << endl;
}
else
{
cout << "YES" << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if ((i == 0 && j == 0) || (i == 0 && j == m - 1) || (i == n - 1 && j == 0) || (i == n - 1 && j == m - 1))
cout << 2 << " ";
else if (i == 0 || j == 0 || i == n - 1 || j == m - 1)
cout << 3 << " ";
else
cout << 4 << " ";
}
cout << endl;
}
}
}
return 0;
}
C. Element Extermination
题目大意:
给定一个数组a,如果a[i]<a[i+1],你可以删除其中一个
经过任意次该操作后能否使得数组中只有一个元素。
思路:
一、使用栈去模拟该过程
1、如果栈空,将元素进栈;
2、栈非空,栈顶元素大于输入元素,输入元素进栈
3、栈非空,栈顶元素小于输入元素,
(1)栈中只有一个元素,跳过输入元素,保持栈顶元素最小,否则将输入元素进栈
(2)取出栈顶的两个元素进行比较,将较小的元素删除,留着较大的去继续匹配剩下的元素,特判一下特殊情况。
二、如果第一个元素小于最后一个元素,即可输出YES
代码:
#include<cstdio>
#include<iostream>
#include<stack>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
stack<int>s;
int n, a;
cin>>n;
for(int i=1; i<=n; i++){
cin>>a;
if(s.empty())
s.push(a);
else if(s.top()>a)
s.push(a);
else{
if(s.size()==1)
continue;
else
s.push(a);
while(1){
int x=s.top(); s.pop();
int y=s.top(); s.pop();
if(y<x)
{
if(s.size()>=1)
s.push(x);
else
s.push(y);
}
else{
s.push(y);
s.push(x);
break;
}
if(s.size()==1)
break;
}
}
}
if(s.size()==1)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
D. Replace by MEX
题目大意:
给定包含n个元素的数组a,每次通过MEX运算获得的值,可以用来替换a中的一个元素,通过不超过2n的操作,可以获得一个递增的数组b,输出操作次数,以及每次替换的a的元素的位置。
思路:
暴力将数组变成1~n
代码:
#include <stdio.h>
#include<iostream>
using namespace std;
#define maxn 1010
int cnt[maxn],a[maxn],ans[maxn<<1],k;
void change(int pos,int val){ //将pos位置变成val,并且更新标记
cnt[a[pos]]--;
cnt[val]++;
a[pos]=val;
}
int main(){
int t,n,i,tot,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++)
cnt[i]=0;
for(i=1;i<=n;i++)
scanf("%d",&a[i]),cnt[a[i]]++;
tot=0,k=0;
for(i=1;i<=n;i++)
if(a[i]==i)
tot++;
if(tot==n){
printf("0\n\n");
continue;
}
while(1){
for(i=0;i<=n;i++)
if(!cnt[i])
break;
if(i==0){
for(j=1;j<=n;j++)
if(a[j]!=j)
break;
ans[++k]=j,change(j,0);
}
else{
ans[++k]=i,change(i,i),tot++;
if(tot==n)break;
}
}
printf("%d\n",k);
for(i=1;i<=k;i++)
printf("%d ",ans[i]);
printf("\n");
}
return 0;
}