51nod-1364 最大字典序排列(线段树)
来源:互联网 发布:单片机种类 编辑:程序博客网 时间:2024/05/22 09:48
原题链接
1364 最大字典序排列
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
收藏
关注
给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?
例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。
Input
第1行:2个数N, K中间用空格分隔(1 <= N <= 100000, 0 <= K <= 10^9)。第2至N + 1行:每行一个数i(1 <= i <= N)。
Output
输出共N行,每行1个数,对应字典序最大的排列的元素。
Input示例
5 612345
Output示例
53124
每次根据k, n算出最远的一个元素j(通过相邻位置的交换能到最前面), 根据cnt线段树查询第j个元素的值,求出下标r, 在根据num线段树求出[1, r]中的最大值,直接输出最大值,把最大值的位置在num[]和cnt[]中赋值为0,相当于没有这个位置,循环操作
#include <bits/stdc++.h>#define maxn 100005#define MOD 1000000007using namespace std;typedef long long ll;int num[maxn<<2], cnt, kk[maxn<<2], p[maxn], vis[maxn];void Build(int j, int l, int r){//建树 if(l == r){scanf("%d", num+j);vis[num[j]] = ++cnt;kk[j] = 1;p[cnt] = num[j];return ;}int mid = (l + r) >> 1;Build(j<<1, l, mid);Build(j<<1|1, mid+1, r);num[j] = max(num[j<<1], num[j<<1|1]);kk[j] = kk[j<<1] + kk[j<<1|1];}int Query(int j, int L, int R, int l, int r){//查询区间[l, r]上的最大值 if(L == l && R == r){return num[j];}int mid = (L + R) >> 1;if(r <= mid) return Query(j<<1, L, mid, l, r);if(l > mid) return Query(j<<1|1, mid+1, R, l, r);return max(Query(j<<1, L, mid, l, mid), Query(j<<1|1, mid+1, R, mid+1, r));}void Update(int j, int L, int R, int e){//下标e所在的元素已经放在前面,则该位置没有元素 if(L == R){num[j] = 0;kk[j] = 0;return ;}int mid = (L + R) >> 1;if(mid >= e) Update(j<<1, L, mid, e);else Update(j<<1|1, mid+1, R, e);num[j] = max(num[j<<1], num[j<<1|1]);kk[j] = kk[j<<1] + kk[j<<1|1];}int Query2(int j, int L, int R, int c){//找到第c个元素的值 if(L == R){return num[j];}int mid = (L + R) >> 1;if(kk[j<<1] >= c) return Query2(j<<1, L, mid, c);return Query2(j<<1|1, mid+1, R, c-kk[j<<1]);}int Query3(int j, int L, int R, int l, int r){//查询[l, r]区间里有多少个元素 if(L == l && R == r){return kk[j];}int mid = (L + R) >> 1;if(r <= mid) return Query3(j<<1, L, mid, l, r);if(l > mid) return Query3(j<<1|1, mid+1, R, l, r);return Query3(j<<1, L, mid, l, mid) + Query3(j<<1|1, mid+1, R, mid+1, r);}int main(){//freopen("in.txt", "r", stdin);int n, k;scanf("%d%d", &n, &k);Build(1, 1, n);int l = 1, t = n;while(k && t){int e = min(k+1, t);int h = Query2(1, 1, n, e); h = vis[h]; h = Query(1, 1, n, 1, h); printf("%d\n", h); h = vis[h]; p[h] = 0; int m = Query3(1, 1, n, 1, h); k -= m - 1; t--; Update(1, 1, n, h);}for(int i = 1; i <= n; i++) if(p[i]) printf("%d\n", p[i]);return 0;}
0 0
- 51nod-1364 最大字典序排列(线段树)
- 51nod 1364 最大字典序排列
- 51Nod-1364-最大字典序排列
- 1364 最大字典序排列
- 最大字典序排列
- 51nod 1364 线段树
- 51nod 1174 区间中最大的数【线段树】
- 51nod 1174 区间中最大的数(线段树)
- 51NOD 1272 最大距离(线段树)
- 51Nod 1174 区间中最大的数 线段树
- 51Nod 1174 区间中最大的数<线段树>
- 51nod 1631 线段树
- 51nod 1672 线段树
- 51nod 1174 区间中最大的数 (线段树+RMQ)
- 51nod 1174 区间中最大的数(线段树)
- 51nod 1174区间中最大的数(线段树)
- 51nod 1260 排列与二叉树
- 51nod 全排列
- Android中onTouchEvent的返回return super.onTouchEvent(ev);数组越界问题解决方法.。。
- 新约——超越大定理
- iOS常用UI控件
- 求逆序数
- Java Modifier 类
- 51nod-1364 最大字典序排列(线段树)
- 通用项目ViewPager的界面搭建
- CTC
- 加强版for循环
- osg 学习之十六:osgconv工具(android支持的纹理格式)
- String类
- LeetCode 137. Single Number II
- Java程序员深度剖析—Java 程序计数器
- AndrewNg机器学习第五周作业:多输出神经网路最后输出结果含义