传送门
C: 问最少要给多少个元素重新赋值, 使得这个数组中最多只有k种数字.
直接记录每个数字出现的次数, 然后从大到小排个序, 从第k+1种那开始选去后面的元素即可.
AC Code
int a[maxn];
bool cmp(int a, int b) {
return a > b;
}
void solve()
{
int n, k;
cin >> n >> k;
for (int i = 1 ; i <= n ; i ++) {
int x; cin >> x ;
a[x]++;
}
sort(a+1, a+1+n, cmp);
int ans = 0;
for (int i = k + 1 ; a[i] ; i ++) ans+=a[i];
cout << ans << endl;
}
D: (好题!)
给定一个数组, 每次操作可以选择一对位置(x, y) , 然后可以ay += ax, 输出这些具体操作使得这个数组变成一个非递减的数组. 操作数在[0, 2*n]范围内都是对的.
我们首先简化下这个问题, 如果这个数组中的元素全是正的或者全是负的, 怎么来整,很明显用前缀或者后缀的思想就可以轻松变成一个非递减数组, 所以我们就找这个数组中的最大值, 然后让每个数都加上这个数这样问题就变成了我们简化过的那个问题了, 通过最大值的正负来确定是前还是后缀即可.
AC Code
const int maxn = 50+5;
int cas=1;
int a[maxn];
void solve()
{
int flag, mx = -1, pos;
int n; scanf("%d", &n);
for (int i = 1 ; i <= n ; i ++) {
scanf("%d", a+i);
if (abs(a[i]) > mx) {
mx = abs(a[i]);
flag = a[i] < 0 ? -1 : 1;
pos = i;
}
}
printf("%d\n", 2*n - 2);
for (int i = 1 ; i <= n ; i ++) {
if (i == pos) continue;
printf("%d %d\n",pos, i);
}
if (flag == 1) {
for (int i = 1 ; i < n ; i ++) {
printf("%d %d\n", i, i+1);
}
}
else {
for (int i = n - 1 ; i >= 1 ; i --) {
printf("%d %d\n", i+1, i);
}
}
}