百度之星 2015 初赛(1) 1002 找连续数

找连续数

 
 Accepts: 401
 
 Submissions: 1911
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
Problem Description

小度熊拿到了一个无序的数组,对于这个数组,小度熊想知道是否能找到一个k 的区间,里面的 k 个数字排完序后是连续的。

现在小度熊增加题目难度,他不想知道是否有这样的 k 的区间,而是想知道有几个这样的 k 的区间。

Input

输入包含一组测试数据。

第一行包含两个整数n,m,n代表数组中有多少个数字,m 代表针对于此数组的询问次数,n不会超过10的4次方,m 不会超过1000。第二行包含n个正整数,第 I 个数字代表无序数组的第 I 位上的数字,数字大小不会超过2的31次方。接下来 m 行,每行一个正整数 k,含义详见题目描述,k 的大小不会超过1000。

Output

第一行输"Case #i:"。(由于只有一组样例,只输出”Case #1:”即可)

然后对于每个询问的 k,输出一行包含一个整数,代表数组中满足条件的 k 的大小的区间的数量。

Sample Input
6 2
3 2 1 4 3 5
3
4
Sample Output
Case #1:
2
2

解题思路:

长度为N的数组中,遍历所有长度为K的区间,对每个区间进行判断,能否满足“排序后是连续的”,暴力判断是直接排序然后判断,复杂度O(klogk),我把它优化成了复杂度O(k)。

将“排序后是连续的”等价为:“最大最小值相差k-1且所有元素不重复”,找出最大最小值是O(k),所有元素不重复使用哈希的方法,也是O(k)。

还有更好的方法,但既然这么暴力都过了,我也就不管这么多了哈哈……

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    int n, m, k;
    cin >> n >> m;
    int a[n];
    int h[1001];
    for(int i = 0; i < n; i++) cin >> a[i];
    cout << "Case #1:" << endl;
    for(int z = 0; z < m; z++) {
        int count = 0;
        cin >> k;
        if(k == 1) {cout << n << endl;continue;}
        int min = a[0], max = a[0];
        for(int i = 1; i < k; i++) {
             if(a[i] > max) max = a[i];
             if(a[i] < min) min = a[i];
        }
        if(max - min == k - 1) {
            bool ok = true;
            memset(h, 0, k * sizeof(int));
            for(int i = 0; i < k; i++) {
                h[a[i]-min] = 1;
            }
            for(int i = 0; i < k; i++) {
                if(h[i] == 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) count++;
        }
        for(int i = 1, iz = i + k - 1; iz < n; i++, iz++) {
            if(a[i - 1] != max && a[i - 1] != min) {
                if(a[iz] > max) max = a[iz];
                if(a[iz] < min) min = a[iz];
            }else {
                min = a[i];
                max = a[i];
                for(int j = i + 1; j <= iz; j++) {
                    if(a[j] > max) max = a[j];
                    if(a[j] < min) min = a[j];
                }
            }
            if(max - min == k - 1) {
                bool ok = true;
                memset(h, 0, k * sizeof(int));
                for(int j = i; j <= iz; j++) {
                    h[a[j]-min] = 1;
                }
                for(int j = 0; j < k; j++) {
                    if(h[j] == 0) {
                        ok = false;
                        break;
                    }
                }
                if(ok) count++;
            }
        }
        cout << count << endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值