中位数

来自http://blog.youkuaiyun.com/w571523631/article/details/72862631(侵删)


总结:对于n个数,移到相同位置,往往是排序后移到中位数那里。。。。

    1952: 地下情报员

      Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 14     Solved: 9    

Description

长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样。 今天小明起来发现自己变成了地下情报员,为了混淆视听,他需要发送一份假电报。

他有一份只有小写字母组成的长度为n × m的样本。领导要求把这个份电报发送出去。 但是小明实在是太懒了,他心想反正也只是用于混淆视听的,所以不如偷点懒。 于是他打了一行长度为n的字符串,然后复制粘贴,生成了m个这样的字符串拼在一起,把这n × m的发送出去。 为了能偷懒,也为了更加逼真,小明希望这长度为n × m的文本与之前的样本的文本距离最短。

对于两个长度均为L的字符串A和B,他们的文本距离可以表示成: 

dist(A,B)=i=1L|A[i]B[i]|


Input

第一行输入T,表示T组测试数据 每组数据第一行两个整数n, m(1 ≤ n × m ≤ 105) 接下来一行为样本,长度为n × m

Output

输出小明能得到的最小文本距离。

Sample Input

2
1 6
abcdef
2 3
aabbcc

Sample Output

9
4

Hint

Source

2017年湖南多校对抗赛第12场

Author

csust

思路:这道题还是比较水的,意思就是分别有n个字符由一个字符移过来,距离是每个字符的差的绝对值,那么显然就是相当于各个字符串移到相同位置的最小距离和,那么就是中位数了,所以把每个位置的字符串中位数求出来就行了

ac代码:

[cpp]  view plain  copy
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<sstream>  
  4. #include<algorithm>  
  5. #include<cstring>  
  6. #include<vector>  
  7. #define LL long long  
  8. #define INF 0x3f3f3f3f  
  9. using namespace std;  
  10. const int maxn = 1e5+100;  
  11. char s[maxn];  
  12. int n,m;  
  13. vector<char>G[maxn];  
  14. int main()  
  15. {  
  16.     int T;  
  17.     scanf("%d",&T);  
  18.     while(T--)  
  19.     {scanf("%d%d",&n,&m);  
  20.         scanf("%s",s);  
  21.         //cout<<s<<endl;  
  22.         for(int i = 0;i<n;i++)  
  23.         {  
  24.             G[i].clear();  
  25.   
  26.         }  
  27.         for(int i = 0;i<n*m;i++)  
  28.         {  
  29.             G[i%n].push_back(s[i]);  
  30.         }  
  31.         for(int i = 0;i<n;i++)  
  32.         {  
  33.             sort(G[i].begin(),G[i].end());  
  34.         }//cout<<s<<endl;  
  35.         int sum = 0;  
  36.         for(int i = 0;i<n*m;i++)  
  37.         {  
  38.             int len = G[i%n].size();  
  39.             sum+=abs(G[i%n][len/2]-s[i]);  
  40.               
  41.         }  
  42.         cout<<sum<<endl;  
  43.     }  
  44. }  

    1947: 突然的灵光

      Time Limit: 2 Sec     Memory Limit: 128 Mb     Submitted: 20     Solved: 15    

Description

长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样。 今天小明早上6点40醒来后发现自己变成了一名高中生,这时马上就要做早操了,小明连忙爬起来 他看到操场密密麻麻的人,突然灵光一闪想到了一个很严肃的问题: 操场上有n个人,第i个人的坐标为(xi, yi),刚开始每个人都站的很松散,现在想把所有人排成一行平行x轴紧挨着的队伍,求所有人需要移动的曼哈顿距离之和的最小值。

Input

多组测试数据 每组数据第一行一个整数n(1 ≤ n ≤ 105), 表示有n个人 接下来n行每行两个整数xi, yi(−109 ≤ xi, yi ≤ 109),表示第i个人的坐标

Output

输出最小代价。

Sample Input

3
1 1
2 1
4 1
4
1 1
1 2
2 1
2 2

Sample Output

1
4

Hint

Source

2017年湖南多校对抗赛第12场

思路:也是道水题很容易想到先把所有的点先聚集到同一条直线上,那么也就相当于把不同的y变成同一个y,那么就是排序后取中位数了,然后就是变成紧凑的了,还是找中位数,因为还是最短距离吗,但是这里不是变成同一个点了,而是变成紧凑的点了,那么还是很简单把中位数这个点从左边逐渐减一,右边的逐渐加一就行了

ac代码:

[cpp]  view plain  copy
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<sstream>  
  4. #include<algorithm>  
  5. #include<cstring>  
  6. #include<vector>  
  7. #define LL long long  
  8. #define INF 0x3f3f3f3f  
  9. using namespace std;  
  10. const int maxn = 1e5+100;  
  11. LL x[maxn];  
  12. LL y[maxn];  
  13. LL n;  
  14. LL slovey()  
  15. {  
  16.     LL yy = y[n/2];  
  17.     LL sum = 0;  
  18.     for(int i = 0 ;i<n;i++)  
  19.     {  
  20.         sum+=abs(yy-y[i]);  
  21.     }  
  22.     return sum;  
  23. }  
  24. LL slovex()  
  25. {  
  26.     LL xx = x[n/2];  
  27.     LL tmp = x[n/2]-1;  
  28.     LL sum = 0;  
  29.     for(int i = n/2-1;i>=0;i--)  
  30.         {  
  31.             sum += abs(x[i]-tmp);  
  32.             tmp--;  
  33.         }  
  34.         tmp = x[n/2]+1;  
  35.         for(int i = n/2+1;i<n;i++)  
  36.         {  
  37.             sum+=abs(x[i]-tmp);  
  38.             tmp++;  
  39.         }  
  40.         return sum;  
  41. }  
  42. int main()  
  43. {  
  44.     while(~scanf("%lld",&n))  
  45.     {  
  46.         for(int i = 0 ;i<n;i++)  
  47.         {  
  48.             scanf("%lld%lld",&x[i],&y[i]);  
  49.         }  
  50.         sort(x,x+n);  
  51.         sort(y,y+n);  
  52.         LL sum = 0;  
  53.         sum+=slovex();  
  54.         sum+=slovey();  
  55.         cout<<sum<<endl;  
  56.     }  
  57. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值