CF_contest371E
来源:互联网 发布:英雄联盟美服mac 编辑:程序博客网 时间:2024/06/03 22:55
CF-contest371E Subway Innovation
http://codeforces.com/contest/371/problem/E
题意:
直线上n个点,设i、j的距离为|Xi - Xj| ,求保留k个点,使得这些点两两之间的距离和最小。(保证无重点,读入非有序) 输出k个点的序号,若有多组则任意.
数据范围:
3<=n<=3e5 ,-1e8<= Xi <= 1e8 , 2<=k<= n-1
简单思路:
1. 排序之后,证明一下必须是连续的k个点才有可能满足。 2. 滑动窗口,大小为k。 3. 预处理出前缀和 或者 区间和,每次增加对窗口内和的影响为(k-1)*Xi - sum[i-k+1..i-1] ,删除同理。
代码:
#include <iostream>#include <string.h>#include <algorithm>#include <math.h>#include <iomanip>#include <cstdio>using namespace std;typedef long long LL;const LL N = 300007;const LL INF = 0x3f3f3f3f;const double Pi = acos(-1);LL n,m,k;LL cc;struct nd{ LL x,id;}s[N];LL sum[N];LL cmp(nd a,nd b){ return a.x<b.x;}int main(){ LL cas=1; while (~scanf("%I64d",&n)) { for (LL i=0;i<n;i++) { scanf("%I64d",&s[i].x); s[i].id=i+1; } scanf("%I64d",&k); sort(s,s+n,cmp); LL tmp=0; LL l=0,r=k-1; sum[0]=s[0].x; for (LL i=1;i<n;i++) sum[i]=sum[i-1]+s[i].x; for (LL i=1;i<k;i++) tmp+=i*s[i].x-sum[i-1]; LL mi=tmp; for (LL i=k;i<n;i++) { LL t=i-k; tmp-=sum[i-1]-sum[t]-(k-1)*s[t].x; tmp+=(k-1)*s[i].x-(sum[i-1]-sum[t]); if (tmp<mi) { mi=tmp; r=i; } } l=r-k+1; for (LL i=l;i<=r;i++) { printf("%I64d",s[i].id); if (i<r) printf(" "); else printf("\n"); } } return 0;}/*31 100 1012511 21 30 40 503*/
0 0
- CF_contest371E
- 如何更改linux(centos)下的Apache http端口号
- centos6.8下使用压缩包安装mysql
- Java语言的虚函数是怎么样的?
- WinHex脚本命令教程--中文版
- 【网络知识】
- CF_contest371E
- linux设备驱动——总线、设备、驱动
- Jquery-validate验证插件自定义验证方法
- Python学习笔记(14)-Python中的进程和线程
- 【C++】bitset的用法
- OKttp带消息头+GSON
- java学习-servlet/filter/listener/interceptor区别与联系(转)
- 命令行查看不同系统的网卡信息
- redis介绍及redis源码安装