题解 | #强迫症#

强迫症

https://ac.nowcoder.com/acm/problem/16301

考虑这个操作的本质,就是任意选一组 i,ji,j,令 aiai+aja_i\leftarrow a_i+a_j

那么一次至多消除一个重复的数字,所以最优的次数就是重复数字的个数。(例如 1 1 1 11~1~1~1 就认为有 33 次重复,2 2 22~2~2 就认为有 22 次重复)

考虑证明这个解存在:

把原序列排序,把重复的数字标记出来,然后从后往前做一波 +=+= 的操作就可以了:

例如:

1 1 1 2 2 2 3 3 31 ~ \color{red}1 ~ 1\color{black} ~ 2 ~ \color{red}2 ~ 2 \color{black}~ 3 ~ \color{red}3 ~ 3

我们直接对红色这些数字进行:

for (int j = len - 1; j >= 1; --j)
  	b[j] += b[j + 1];

的操作,即可把原序列变成:

1 12 11 2 10 8 3 6 31 ~ \color{red}12 ~ 11\color{black} ~ 2 ~ \color{red}10 ~ 8 \color{black}~ 3 ~ \color{red}6 ~ 3

肉眼可见这种方法一定是对的。(注意一开始的那一个还要加回来一个最大的 1212

#include<cstdio>
#include<algorithm>
int init(){
	char c = getchar();
	int x = 0, f = 1;
	for (; c < '0' || c > '9'; c = getchar())
		if (c == '-') f = -1;
	for (; c >= '0' && c <= '9'; c = getchar())
		x = (x << 1) + (x << 3) + (c ^ 48);
	return x * f;
}
void print(int x){
	if (x < 0) x = -x, putchar('-');
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int N = (int) 1e5 + 5;
int a[N];
int main(){
    int n = init();
    for (int i = 1; i <= n; ++i)
        a[i] = init();
    std::stable_sort(a + 1, a + 1 + n);
    int tot = 0;
    for (int i = 1; i <= n; ++i)
        if (a[i] == a[i - 1]) ++tot;
    print(tot), putchar('\n');
}
全部评论

相关推荐

11-27 17:08
已编辑
牛客_产品运营部_私域运营
腾讯 普通offer 24k~26k * 15,年包在36w~39w左右。
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
10-17 12:16
同济大学 Java
7182oat:快快放弃了然后发给我,然后让我也泡他七天最后再拒掉,狠狠羞辱他一把😋
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务