hdoj 5247 找连续数 【思维】
2016-01-15 22:21
447 查看
找连续数
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1169 Accepted Submission(s): 418
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
思路:一开始想法是考虑k区间的右端点,用dp来做。
设置dp[i][k]为前i位满足的k区间个数。那么dp[i][k] = dp[i-1][k] + May[i][k]。May[i][k]表示区间[i-k+1, i]是否满足的bool型。判定区间是否满足——没有重复元素的前提下最大值
- 最小值 == 区间长度 - 1。
写着写着发现写乱了,先求每个位置的May[i][],然后再求每个k的dp[][k]。。。重想重写。。。
那反过来考虑左端点,只要我们推出在某个位置pos >= i使得[i, pos]区间不再满足,那么>pos的区间也不会满足。
那么只需要在每个位置递推一次所有的k,就可以全部搞出来。O(nk)就搞定了。这回思路清晰多了。。。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <string> #define INF 0x3f3f3f3f #define eps 1e-8 #define MAXN (10000+10) #define MAXM (200000+10) #define Ri(a) scanf("%d", &a) #define Rl(a) scanf("%lld", &a) #define Rf(a) scanf("%lf", &a) #define Rs(a) scanf("%s", a) #define Pi(a) printf("%d\n", (a)) #define Pf(a) printf("%.2lf\n", (a)) #define Pl(a) printf("%lld\n", (a)) #define Ps(a) printf("%s\n", (a)) #define W(a) while(a--) #define CLR(a, b) memset(a, (b), sizeof(a)) #define MOD 1000000007 #define LL long long #define lson o<<1, l, mid #define rson o<<1|1, mid+1, r #define ll o<<1 #define rr o<<1|1 #define PI acos(-1.0) using namespace std; //int Max[MAXN][1001], Min[MAXN][1001], dp[MAXN][1001]; map<int, bool> fp; int ans[1001], a[MAXN]; int main() { int kcase = 1, n, m; while(scanf("%d%d", &n, &m) != EOF) { for(int i = 1; i <= n; i++) Ri(a[i]); CLR(ans, 0); for(int i = 1; i <= n; i++) { fp.clear(); int Max = 0, Min = INF; for(int k = 1; k <= 1000 && i + k - 1 <= n; k++) { if(fp[a[i+k-1]]) break; fp[a[i+k-1]] = 1; Max = max(Max, a[i+k-1]); Min = min(Min, a[i+k-1]); if(Max - Min == k - 1) ans[k]++; } } printf("Case #%d:\n", kcase++); W(m) { int k; Ri(k); Pi(ans[k]); } } return 0; }
相关文章推荐
- iOS 学习第八天 C语言 二维数组
- 数据库——基础(数据库操作,表格操作)——增加高级查询
- hdoj 5246 超级赛亚ACMer 【贪心+二分】
- ie打开下载对话框分析--发文于2013.10.28
- hdoj 1755 A Number Puzzle 【STL】
- PCB学习第一讲
- com的小笔记--发文于2013-10-24
- listview中实现item播放音乐的进度显示
- didReceiveMemoryWarning
- 搞清楚学习Web的目的,是为了推广自己的产品和服务,不是为了替人接单做网页
- 《侣行》三季合集下载
- iOSCore Location地理定位的简单实用
- ubuntu 14.04 改网卡IP为静态IP
- MySQL高级十六——内存优化
- 同步异步,阻塞非阻塞 和nginx的IO模型
- PCB布线技巧
- 常用的正则表达式验证
- 触发器类 , 指针函数
- Understanding Linux /proc/id/maps
- 按顺序比较大小