UVa11491- Erasing andWinning(从一题看多解)
2016-09-26 23:59
399 查看
UVa11491- Erasing andWinning
题意:给定一个n位数,删除d位数字,求删除后最大的数。
分析:删除d位数字使得剩下的数字最大,也就是选出n-d个数,容易知道,每次只要在区间内找到最大的那个数就行了,方法特别多,不过大多思想差不多,只不过实现不同罢了,从一题看多解,也同时感受到了不同方法的好坏。
1、当然,最容易想到的就是暴力,这个不多说,不过值得一提的是,和自己料到的一样,用STL超时了,改用循环就过了,(其实也跑了790ms),我就纳闷了,这不才1e5个数位吗….
2、既然是区间找最值,那么如果用高效的数据结构的话,那么就是线段树了,维护当前区间内最大值的下标就行了,查询n-d次就行了。
3、另外一种数据结构便是单调队列,同样维护最大值的下标,如果当前最大值的下标不在所选区间内,那么删除,总共选n-d个位就行了,当然还可以用优先队列,不过实现起来差不多,但明显单调队列更优。
4、采用贪心的策略,边输入边处理,这种巧妙的方式是在另一位博主的博客中学习到的,感觉其实思想和单调队列差不多,只不过那么相对而言更好一点。
http://blog.csdn.net/u014800748/article/details/43671343
上面便是该博主巧妙的解决方式。
题意:给定一个n位数,删除d位数字,求删除后最大的数。
分析:删除d位数字使得剩下的数字最大,也就是选出n-d个数,容易知道,每次只要在区间内找到最大的那个数就行了,方法特别多,不过大多思想差不多,只不过实现不同罢了,从一题看多解,也同时感受到了不同方法的好坏。
1、当然,最容易想到的就是暴力,这个不多说,不过值得一提的是,和自己料到的一样,用STL超时了,改用循环就过了,(其实也跑了790ms),我就纳闷了,这不才1e5个数位吗….
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define INF 0x3f3f3f3f #define LL long long #define N 1000010 using namespace std; char s ; int d, n, x, y; int main() { while (~scanf("%d %d", &n, &d), n || d){ getchar(); int i = 0; while ((s[++i] = getchar()) != '\n'); x = 1, y = d+1; for (int cnt = 1; cnt <= n-d; cnt++){ int pos = 0; for (int i = x; i <= y; i++) if (s[i] > s[pos]) pos = i; putchar(s[pos]); x = pos+1, y = d+cnt+1; } putchar('\n'); } return 0; }
2、既然是区间找最值,那么如果用高效的数据结构的话,那么就是线段树了,维护当前区间内最大值的下标就行了,查询n-d次就行了。
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define INF 0x3f3f3f3f #define LL long long #define N 100010 using namespace std; char s ; int d, n, x, y; int c[N<<2]; void build(int rt, int l, int r) { if (l == r){ c[rt] = l; return ; } int m = l+(r-l)/2; build(rt<<1, l, m); build(rt<<1|1, m+1, r); if (s[c[rt<<1]] >= s[c[rt<<1|1]]) c[rt] = c[rt<<1]; else c[rt] = c[rt<<1|1]; } int query(int rt, int l, int r) { if (x <= l && r <= y) return c[rt]; int m = l+(r-l)/2, pos = 0; if (x <= m){ int t = query(rt<<1, l, m); if (t != -1 && s[t] > s[pos]) pos = t; } if (y > m){ int t = query(rt<<1|1, m+1, r); if (t != -1 && s[t] > s[pos]) pos = t; } return s[pos]==0 ? -1 : pos; } int main() { s[0] = 0; int k = 0; while (scanf("%d %d", &n, &d), n || d){ scanf("%s", s+1); build(1, 1, n); x = 1, y = d+1; int t = 0; for (int cnt = 1; cnt <= n-d; cnt++){ int pos = query(1, 1, n); putchar(s[pos]); x = pos+1, y = d+cnt+1; } putchar('\n'); } return 0; }
3、另外一种数据结构便是单调队列,同样维护最大值的下标,如果当前最大值的下标不在所选区间内,那么删除,总共选n-d个位就行了,当然还可以用优先队列,不过实现起来差不多,但明显单调队列更优。
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define LL long long #define INF 0x3f3f3f3f using namespace std; int q[100010]; int fro, rea; char s[100010]; void in(int i) { while (fro != rea && s[q[rea-1]] < s[i]) rea--; q[rea++] = i; } int main() { int n, d; while (scanf("%d %d", &n, &d), n+d){ scanf("%s", s+1); fro = rea = 0; int pos = 0, i; for (i = 1; i <= d; i++) in(i); for (; i <= n; i++){ in(i); while (q[fro] <= pos) fro++; putchar(s[q[fro]]); pos = q[fro]; } putchar('\n'); } return 0; }
4、采用贪心的策略,边输入边处理,这种巧妙的方式是在另一位博主的博客中学习到的,感觉其实思想和单调队列差不多,只不过那么相对而言更好一点。
http://blog.csdn.net/u014800748/article/details/43671343
上面便是该博主巧妙的解决方式。
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define INF 0x3f3f3f3f #define LL long long #define N 100010 using namespace std; char s ; int n, d, j; int main() { while (j = 0, scanf("%d %d", &n, &d), n || d){ getchar(); for (int i = 0; i < n; i++){ char c = getchar(); while (j > 0 && i-j < d && s[j] < c) j--; if (j+d < n) s[++j] = c; } s[++j] = 0; puts(s+1); } return 0; }
相关文章推荐
- 从一个n位数中选出m位按顺序组成新数并使其最大 || Erasing and Winning UVA - 11491
- UVA 11491 Erasing and Winning 奖品的价值 (贪心)
- uva 11491 Erasing and Winning
- Uva - 11491 - Erasing and Winning
- uva 11491 Erasing and Winning 奖品的价值(贪心)
- Uva - 11491 - Erasing and Winning
- UVA 11491 Erasing and Winning
- UVa 11491 - Erasing and Winning(贪心)
- UVA-11491 Erasing and Winning (单调队列)
- 【思路、优化】UVa 11491 - Erasing and Winning
- UVa:11491 Erasing and Winning(单调栈)
- uva 11491 - Erasing and Winning
- UVA - 11491 Erasing and Winning 贪心
- UVa 11491 - Erasing and Winning ( 优先队列模拟 )
- UVa 11491 Erasing and Winning (贪心,单调队列或暴力)
- UVA - 11491 Erasing and Winning
- Uva 11491 Erasing and Winning(贪心)
- UVA 11491 Erasing and Winning(贪心)
- (贪心+栈)UVa 11491 Erasing and Winning
- Erasing and Winning UVA - 11491