A 题目链接:Problem - A - Codeforces
input:
4
4
3 3 6 6
2
10 10
5
1 2 3 4 5
3
1 4 4
output:
YES
3 6 3 6
NO
YES
2 4 1 5 3
YES
1 4 4
题意:
如果数组 a 中至少存在一个数,满足这个数等于其前面所有数的和(ai == a1 + a2 + ...+ ai-1),则称该数组为 ugly 数组。现给出一个长度为 n 的数组 a ,判断能否对该数组进行排序,使其不为 ugly 数组。若可以,输出 YES ,并输出任意一种不为 ugly 的形式,否则输出 NO .
思路:
首先只有一种情况不满足条件:数组中所有元素相等。这种情况下,前两个数一定相等,不满足条件。
剩下的情况,我们将数组从大到小排序,然后先输出 an ,再依次输出 a1 ~ an-1 即可。
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
int t,n;
int a[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
cin>>a[1];
int s=a[1];
bool f=0;
for(int i=2;i<=n;i++)
{
cin>>a[i];
if(a[i]!=s)
f=1;
}
sort(a+1,a+n+1,cmp);
if(!f)
{
cout<<"NO"<<endl;
}
else
{
cout<<"YES"<<endl;
cout<<a[n]<<" ";
for(int i=1;i<=n-1;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
}
}
return 0;
}
B 题目链接:Problem - B - Codeforces
input:
2
2
3
output:
1 3
4 2
1 3 4
9 2 7
5 8 6
题意:
一个方阵的 beauty ,意为该方阵所有相邻数对的差的绝对值种类数。
给定一个 n ,试构造一个 n * n 的方阵,填数为 1 ~ n * n(每个数出现且仅出现一次)使该方阵 beauty 最大。
思路:
显而易见,一个 n * n 方阵beauty 最大值应为 n * n - 1(1 ~ n * n - 1)。
所以我们按最大值、最小值、次大值、次小值串联排列即可。我的排列方式如下:
实现见代码。
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
int t,n;
int a[100][100];
int b[10000];
bool vis[10000];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
int s=n*n;
memset(vis,0,sizeof vis);
memset(a,0,sizeof a);
int i=1,j=1;
int k=1;
bool f=0;
while(k<=n*n)
{
a[i][j]=s;
vis[s]=1;
s=n*n-s+1;
if(vis[s]==1)
{
s--;
}
if(j==n&&a[i][j-1]!=0)
{
i++;
f=1;
continue;
}
if(j==1&&a[i][j+1]!=0)
{
i++;
f=0;
continue;
}
if(f==0)
{
j++;
}
else
{
j--;
}
k++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
return 0;
}
C 题目链接:Problem - C - Codeforces
input:
5
4 401
100 100 200 1
3 2
1 2 3
5 0
1 1 1 1 1
4 0
0 1 1 1
4 4
1 2 2 1
output:
1
2
6
4
1
题意:
现在你正在和 n 个人(共 n + 1个人)进行比赛,这 n 个人编号为 1 ~ n。
每两个人之间比赛一场,其他人之间的比赛,编号大的人获胜。
你与其他 n 个人的比赛比较特殊。对于第 i 个人,你如果向取得胜利,必须花费至少 ai 分钟时间准备比赛,否则会输。
你共有 m 分钟的准备时间,同一时间只能准备一场比赛。
问如何分配时间,使得你的排名最考前(按胜场数决定排名,胜场数越高排名越靠前),输出你的最优排名。
如果存在若干名选手胜场一致,那么其排名一致(比如有5个人,胜场分别为 0 2 2 2 4,那么选手排名为 5 2 2 2 1).
思路:
首先,我们要想办法取得最多的胜场,这是毋庸置疑的。我们将所有人的准备时间从小到大排序,然后选择优先击败准备时间小的选手,直至准备时间 m 不够用为止。假设此时胜场为 k。
我们可以知道,在与我们比试之前,其他 n 位选手的比赛胜场为 0 1 2 ...... n - 1,我们与 n 个选手比赛,产生了 k 个胜场,也就是说会有 k 位选手败给我们,胜场数不变,其他 n - k位选手赢了我们,胜场数+1.现在我们的排名只有可能往前进一步,有以下三种情况:
1.我们获得 k 个胜场,编号为 k + 1的选手先前也是获得了 k 个胜场,并输给了我们,胜场数未变,这时候该选手和我们排名并列第 n - k 名
2.我们获得 k 个胜场,编号为 k + 1的选手先前也是获得了 k 个胜场,并赢了我们,胜场数+1,此时我们需要判断能否选择将我们的胜场中花费时间最多的那一场,换成赢第 k + 1位选手:
(1) 如果够,结果同 1 ,我们和该选手并列第 n - k 名。
(2)如果不够,我们排第 n - k + 1名。
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=5e5+10;
int t,n;
ll m;
struct node{
int id;
int v;
}a[N];
int win[N];
int vv[N];
bool cmp(node a,node b)
{
return a.v<b.v;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
a[i].id=i;
cin>>a[i].v;
vv[i]=a[i].v;
win[i]=i;
}
sort(a+1,a+n+1,cmp);
int k=1;
int cnt=0;
while(k<=n)
{
if(m>=a[k].v)
{
m-=a[k].v;
win[a[k].id]--;
++k;
++cnt;
}
else
{
break;
}
}
if(cnt==n)
{
cout<<1<<endl;
}
else if(win[cnt+1]==cnt)
{
cout<<n-cnt<<endl;
}
else
{
if(m+a[k-1].v>=vv[cnt+1])
{
cout<<n-cnt<<endl;
}
else
{
cout<<n-cnt+1<<endl;
}
}
}
return 0;
}
/*
1
3 2
1 2 3
*/