T1-明明的随机数
排序 + 去重
显然,对于去重来说,桶排序无疑是一种好的方式,对于此题的数据范围完全够用。
#include<bits/stdc++.h>
using namespace std;
int x[101],a[1001] = {0};
int main(){
int n;
scanf("%d",&n);
int maxx = -0x3f3f3f;
for(int i = 0;i < n;i++){
scanf("%d",&x[i]);
a[x[i]] ++;
maxx = max(maxx , x[i]);
}
int ans = 0;
for(int i = 0;i <= maxx;i++){
if(a[i] > 0){
ans++;
}
}
printf("%d\n",ans);
for(int i = 0;i <= maxx;i++){
if(a[i] > 0){
printf("%d ",i);
}
}
return 0;
}
然而,使用C++自带库函数也十分简单
#include<bits/stdc++.h>
using namespace std;
int a[1001];
int main(){
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
}
sort(a + 1,a + n + 1);
int ans = unique(a + 1,a + n + 1) - a - 1;
printf("%d\n",ans);
for(int i = 1;i <= ans;i++){
printf("%d ",a[i]);
}
return 0;
}
注意:unique:将数组中不重复元素前移
T2: 简单冒泡+判断次数
Q:为什么能保证【移动次数最小】?
A:冒泡排序的每一次交换都是必要的。
T3: masses number:建议使用桶排序
T4: knumber:可以使用STL中nth_element()函数
nth_element(a,a+2,a+9),将下标为2,也就是第3个数放在正确的位置,求的是第3小的数a[2]。(下标从零开始,返回第i+1小)
nth_element(a,a+k,a+n),函数把下标为k的元素放在了正确位置,对其它元素并没有排序,当然k左边元素都小于等于它,右边元素都大于等于它,所以可以利用这个函数快速定位某个元素。
nth_element(a,a+2,a+9,comp)
nth_element()为什么快呢:因为没排序
注意特判
T5≈T4
T6:scholar 没什么好讲的
T7: 这道题你也想用桶排吗??
1.5*10^9……
直接sort(long long*)就成(对于时间限制没那么高)
T8,T9(重头戏)
对于T8-> 使用“数学方法”证明取中位数时有最小和。
对于T9-> x,y分开判断。
纵向与T8类似
横向:
先对所有的X坐标从小到大排序,排序后,为了放便描述,我们依然用X1,X2,X3……Xn-1,Xn代表士兵的位置(但是要注意这个是已经排好序的),假如最后所有士兵站的位置为X,X+1,X+2……X+n-1,那么即是求|X1-X|+|X2-(X+1)|+|X3-(X+2)|+……|Xn-(X+n-1)|的最小值,将算式变形,即为|X1-X|+|(X2-1)-X|+|(X3-2)-X|+……|(Xn-(n-1))-X|,同上可以看出,X即为X1,X2-1,X3-2……Xn-(n-1)的中位数,据此可以求得X方向的最小移动步数。
T9代码
#include<bits/stdc++.h>
using namespace std;
int posx[10005];
int posy[10005];
int main(){
int n;
while (scanf("%d",&n)!=EOF){
for (int i=0;i<n;i++){
scanf("%d%d",&posx[i],&posy[i]);
}
sort(posx,posx+n);
sort(posy,posy+n);
for (int j=0;j<n;j++){
posx[j] = posx[j] - j;
}
sort(posx, posx + n);
int mx = posx[n / 2];
int my = posy[n / 2];
int count = 0;
for (int k = 0; k < n; k++){
count = count + abs(posx[k] - mx);
count = count + abs(posy[k] - my);
}
printf("%d",count);
}
return 0;
}