山东理工大学第八届ACM校赛——选拔忧虑

来源:互联网 发布:网络钢琴 编辑:程序博客网 时间:2024/04/29 12:49

选拔忧虑

看见这个题 不少同学都想到了O(nk)的做法——把支持和一共的人数存在数组里 对每一个范围 跑k次加和 求出这个范围的支持率 整个n范围内的最大的支持率就是这个题的结果 但是且慢 这个题的n, k小于1000 还可以这样做 如果n,k给到一万、 十万的话 又该怎么办呢 那时候再用O(nk)的做法肯定会超时(当然这个题并不会)

其实 我们可以对数组做一些小小的改动 就可以大幅降低时间复杂度 只要让数组的对应位置存的不是这个位置的人数 而是从第一个一直累加到这个位置的人数就行 这样 如果想知道这个位置前k的位置到这个位置的人数 只要用数组的当前位置的人数减去k前的数组的人数就可以 这样可以剩下k次加和的过程 时间复杂度可以直接降低至O(n) 当然 用这个方法要注意 累加的和不要超过数组能表示的数据范围 

知道这个方法后 其实这个题目就很简单了 直接上代码

#include <stdio.h>#include <string.h>int main(){int i, n, k, c;int sum[1111], ok[1111];double h;while (~scanf("%d%d", &n, &k)){memset(sum, 0, sizeof sum);//sum数组存到当前位置的总人数之和memset(ok, 0, sizeof ok);//ok数组存到当前位置的支持人数之和h = 0;//h用来存整个范围内最大的支持率for (i = 0; i < n; i++){scanf("%d", &c);sum[i] = i? sum[i-1] + c : c;}for (i = 0; i < n; i++){scanf("%d", &c);ok[i] = i? ok[i-1] + c : c;}for (i = k - 1; i < n; i++){h = h>(ok[i]-ok[i-k])*1.0/(sum[i]-sum[i-k]) ? h : (ok[i]-ok[i-k])*1.0/(sum[i]-sum[i-k]);}printf("%.4lf\n", h);}return 0;}


0 0