hdu 5247 找连续数 && 百度之星初赛第一场1002

题目:

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

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

Input
输入包含一组测试数据。

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


题解:

1.这道题据说'暴力枚举 + rmq + 离散化'就可以过

2.懒得写rmq,用map枚举了一遍就超时了

3.发现网上用set暴力过的,学习了一下他们的方法

4.思路是对于一段区间,如果这个区间的最大值 - 最小值 + 1 == 区间size && 不包含相同的数,那么这个区间就是满

足条件

5.那么怎么枚举呢?我开始想的就是先枚举所有大小为k(k取值分别为1,2,3,4.....)的区间,但是我需要知道是否有

重复的数,并且需要知道最大值,最小值,用map可以做到不过超时了,不够优

6.网上KinderRiven神的枚举方式是:按每个区间初始的位置开始枚举,比如从index等于0处枚举k(0---1000),再在

index等于1处继续枚举k,这样的优点就是一但碰到重复的数时,不需要费力记录,直接跳出循环,因为如果ki已经存

相同的数时,那么对于ki+1必定也存在重复的数

总结:

1.依旧是那个亘古不变的问题,为啥我就想不到呢,我觉得,还是考虑问题不够全面,没有宏观的思考这个问题,统

共只有这两种枚举方式,我想到其中一种就非要一路走到黑。

2.如果最开始想暴力枚举的时候就考虑到两种枚举方式,都作简单的思考,那么第二种方式应该很快就能想到,因为

既好写,又高效

3.怎么解决这个问题呢,以前刚写程序的时候,怕忘写大括号的反括号(因为那时候用的dev没有codeblock这么智

能),所以我每次写大括号的时候,一写就是写一对。

4.那么,如果考虑问题的时候,我也养成每走一步,都把所有解决方式罗列出来,是不是就能更快的找到更优的解题

方法呢。嗯,值得尝试


#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 10005;
setse;
set :: iterator it1,it2;
int n,m;
int ans[MAXN];
LL arr[MAXN];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0;i < n;i++)
        scanf("%I64d",&arr[i]);
    for(int j = 0;j < n;j++)
    {
        se.clear();
        for(int i = 0;i < 1000 && i + j < n;i++)
        {
            if(!se.count(arr[j + i]))
                se.insert(arr[j + i]);
            else
                break;
            int minn = *(se.begin());
            int maxn = *(se.rbegin());
            if(maxn - minn == se.size() - 1)
                ans[i]++;
        }
    }
    printf("Case #1:\n");
    while(m--)
    {
        int k;
        scanf("%d",&k);
        printf("%d\n",ans[k - 1]);
    }
}




你可能感兴趣的:(enumerate)