51Nod-1364-最大字典序排列
2017-06-16 02:31
197 查看
ACM模版
描述
题解
典型的贪心,每次都找能够移过来前边的最大值,记住是能够,所以我们需要在剩余的操作次数可以满足的范围内找到最大值,不断查找,不断移动输出,此时,存在一个问题,N、K 太大了,每次查找和移动的花费特别高,所以此时我们应该借助比较高级的数据结构来实现快速查找,酱紫,我们自然会想到线段树之类的数据结构,这个数据结构涉及到结点更新、结点查找、区间求和等操作,所以要小心维护哦~~~代码
#include <algorithm> #include <iostream> #include <cstdio> #include <cstring> #define lson root << 1 #define rson root << 1 | 1 #define ll long long #define clr(a, b) memset(a, b, sizeof(a)) using namespace std; const int MAXN = 1e5 + 10; int N, K; int a[MAXN]; struct node { int l, r, mid; int pos, sum; int max; } tree[MAXN << 2]; void push_up(int root) { if (tree[lson].max >= tree[rson].max) { tree[root].max = tree[lson].max; tree[root].pos = tree[lson].pos; } else { tree[root].max = tree[rson].max; tree[root].pos = tree[rson].pos; } tree[root].sum = tree[lson].sum + tree[rson].sum; } void build_tree(int root, int l, int r) { tree[root].l = l; tree[root].r = r; tree[root].mid = (l + r) >>1; tree[root].sum = 0; if (l == r) { tree[root].sum = 1; tree[root].max = a[l]; tree[root].pos = l; return ; } build_tree(lson, l, tree[root].mid); build_tree(rson, tree[root].mid + 1, r); push_up(root); } int Max, Pos; // 结点更新 void update(int root, int pos) { if (tree[root].l >= pos && tree[root].r <= pos) { tree[root].max = 0; tree[root].sum = 0; return ; } int mid = tree[root].mid; if (pos <= mid) { update(lson, pos); } else { update(rson, pos); } push_up(root); } // 查找最大值及其位置,值相等,取较小位置 void query(int root, int l, int r) { if (tree[root].l >= l && tree[root].r <= r) { if (Max < tree[root].max) { Max = tree[root].max; Pos = tree[root].pos; } return ; } int mid = tree[root].mid; if (l <= mid) { query(lson, l, r); } if (r > mid) { query(rson, l, r); } push_up(root); } // 结点查找 int query_k(int root, int k) { if (tree[root].l == tree[root].r) { return tree[root].l; } if (tree[lson].sum >= k) { return query_k(lson, k); } else { return query_k(rson, k - tree[lson].sum); } } // 区间求和 int query_sum(int root, int l, int r) { if (tree[root].l >= l && tree[root].r <= r) { return tree[root].sum; } int ans = 0; if (l <= tree[root].mid) { ans += query_sum(lson, l, r); } if (r > tree[root].mid) { ans += query_sum(rson, l, r); } return ans; } int main() { while (cin >> N >> K) { a[0] = 0; for (int i = 1; i <= N; i++) { scanf("%d", a + i); } build_tree(1, 1, N); int cnt = 1; while (K > 0 && cnt <= N) { Max = 0, Pos = N; if (cnt + K >= N) { query(1, 1, N); update(1, Pos); K -= query_sum(1, 1, Pos); printf("%d\n", Max); } else { int pos = query_k(1, K + 1); query(1, 1, pos); update(1, Pos); K -= query_sum(1, 1, Pos); printf("%d\n", Max); } a[Pos] = -1; cnt++; } for (int i = 1; i <= N; i++) { if (a[i] != -1) { printf("%d\n", a[i]); } } } return 0; }
相关文章推荐
- 51nod 1364 最大字典序排列
- 51nod 1364 最大字典序排列(线段树)
- 1364 最大字典序排列
- 51nod-1364 最大字典序排列(线段树)
- USTC机试—从键盘输入 N,建立 N*N矩阵,每个元素是一个字符串,为每个元素赋值。然后求 出按字典序排列最大的元素所在的行列。
- 最大字典序排列
- 51nod1364 最大字典序排列
- 51Node 1364--- 最大字典序排列(树状数组)
- 51nod 1296 有限制的排列
- 51nod_1100_斜率最大
- 51nod 1270 数组的最大代价 绝对值取极值问题
- [51nod 1129] 字符串最大值(kmp)
- 排列的字典序问题
- 51nod 1442 士兵的旅行(最大流)
- 51nod 1179:最大的最大公约数
- HDU3729 I'm Telling the Truth(字典序最大的最大流)
- 51Nod-1011-最大公约数GCD
- 给定n个字符串,请对n个字符串按照字典序排列
- String Problem --- hdu3374(kmp、字典序最大与最小)
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。