csu 1774 慷慨的奖励[双向链表]
来源:互联网 发布:金蝶房地产软件 编辑:程序博客网 时间:2024/05/18 01:45
CSU 1774 慷慨的奖励
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1774
题意: 给定长度为N的0~9数字字符串,从中删掉D个字符,求能够构成的最大的数字。
思路:D个字符一个个的删,直到全部删完:
- 如果当前这个字符比下一个字符还小,删之, 即先删字符串的升序部分;
- 删完之后,如果删完的新序列前面又构成了升序,删掉前面的升序部分;
- 删到最末尾了,然后全部是降序了,那么毫无疑问,从末尾往前删;
这样算下来,负责度就是O(N)。
例如:N=8,K=5, 序列为14231432。
- 首先删掉第一个1,得:4231432;
- 然后删掉第一个2,得:431432;
- 然后删掉第一个1,得:43432;
- 检测到之前新增了一个升序部分,向前删掉第一个3,得:4432;
- 一直遍历到最后,已经构成了一个降序序列了,还要删一个,那么就从末尾向前删,得:443,结束。
步骤是每次选择出当前的最高位:
例如:
N=8,K=5, 序列为14231432。
- 首先从前6个字符142314中(PS:因为最高位不可能是最后面两个数字)选出最大的数字:4, 下标为1;
- 然后从下标为2的字符开始,在23143选出最大的数字:4,记录下标为5;
- 然后从下标为5的字符开始,在32中选出最大的数字:3,结束。
/** * 思路一: 双向链表 * Author:XXW **/#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w",stdout)const int maxn = 1e5 + 5;int N, D;char str[maxn];struct Node { int prior, rear;} nodes[maxn];void del(int x) { int a = nodes[x].prior; int b = nodes[x].rear; if(a == -1) { nodes[b].prior = -1; } else { nodes[a].rear = b; } if(b == -1) { nodes[a].rear = -1; } else { nodes[b].prior = a; }}int main() {#ifndef ONLINE_JUDGE FIN;#endif // ONLINE_JUDGE while(~scanf("%d %d", &N, &D) && N) { scanf("%s", str); nodes[0].prior = -1; nodes[0].rear = 1; nodes[N - 1].prior = N - 2; nodes[N - 1].rear = -1; for(int i = 1; i < N - 1; i++) { nodes[i].prior = i - 1; nodes[i].rear = i + 1; } int pos = 0, phead = 0, cnt = D; while(cnt > 0) { int np = nodes[pos].rear; if(np != -1 && str[pos] < str[np]) { del(pos); if(pos == phead) phead = np; pos = np; cnt --; } else if(np != -1 && str[pos] >= str[np]) { pos ++; continue; } else if(np == -1) { pos = nodes[pos].prior; del(nodes[pos].rear); cnt --; } int pp = nodes[pos].prior; while(cnt > 0 && pp != -1 && str[pos] > str[pp]) { del(pp); pp = nodes[pos].prior; cnt --; } if(pp == -1) phead = pos; } for(int i = 0, pos = phead; i < N - D; i ++) { printf("%c", str[pos]); pos = nodes[pos].rear; } puts(""); } return 0;}
/** * 思路二: 线段树求区间最值 * Author:XXW **/#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w",stdout)#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1const int maxn = 1e5 + 5;int N, D;char str[maxn];struct Node { int prior, rear;} nodes[maxn];char segTree[maxn << 2];int pos[maxn << 2];void build(int l, int r, int rt) { if(l == r) { segTree[rt] = str[l]; pos[rt] = l; return; } int mid = (l + r) >> 1; build(lson); build(rson); if(segTree[rt << 1] >= segTree[rt << 1 | 1]) { pos[rt] = pos[rt << 1]; } else { pos[rt] = pos[rt << 1 | 1]; } segTree[rt] = max(segTree[rt << 1], segTree[rt << 1 | 1]);}char ch;int _prev;char query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { if(ch < segTree[rt]) { ch = segTree[rt]; _prev = pos[rt]; } return segTree[rt]; } int mid = (l + r) >> 1; char ret = -1; if(L <= mid) { ret = max(ret, query(L, R, lson)); } if(R > mid) { ret = max(ret, query(L, R, rson)); } return ret;}int main() {#ifndef ONLINE_JUDGE FIN;#endif // ONLINE_JUDGE while(~scanf("%d %d", &N, &D) && N) { scanf("%s", str + 1); D = N - D; build(1, N, 1); _prev = 0; for(int i = 1; i <= D; i++) { int l = _prev + 1, r = N - (D - i); ch = -1; char res = query(l, r, 1, N, 1); printf("%c", res); } puts(""); } return 0;}
1 0
- csu 1774 慷慨的奖励[双向链表]
- CSU - 1774 慷慨的奖励(模拟链表)
- csu 1774 慷慨的奖励(模拟链表,贪心)
- CSU1774-慷慨的奖励-链表
- csu 1329 一行盒子(双向链表模拟)
- CSU 1329: 一行盒子(双向链表)经典 13年省赛题
- 一头慷慨赴死的猪
- “慷慨的上帝” vs “吝啬的上帝”
- 笑话之“一头慷慨赴死的猪”。
- 一头慷慨赴死的猪(转载)
- 双向链表的排序
- 双向链表的查找
- 双向链表的建立
- 双向链表的实现
- 通用的双向链表
- 双向链表的实现
- 双向链表的实现
- 双向链表的建立
- H - Wireless Network
- B - Ubiquitous Religions
- java多线程(一)多线程基础
- synchronized 的用法
- Linux 同步网络时间
- csu 1774 慷慨的奖励[双向链表]
- UVALive 4636 B - Cubist Artwork
- Linux下EasyPanel版本安装及升级
- Chromium分发输入事件给WebKit处理的过程分析
- extern 用法总结
- 实战retrofit
- 通过源代码认识Context的作用
- B树、B+树与B*树简介
- handler机制详解