首页 > 代码库 > 51nod 1364 最大字典序排列(线段树)
51nod 1364 最大字典序排列(线段树)
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
/*51nod 1364 最大字典序排列(线段树)problem:给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。solve:贪心的思想. 从1~n维护第i个数尽可能大. 就成了在[i+1,k+i]中查找最大值. 然后把找到的数从后面的数组中删除插到前面.因为我的删除是用num来表示,所以每次都要先找到对应区间的边界位置. 然后在计算移动过去需要多少步. 直到操作结束hhh-2016/09/04-11:16:36*/#pragma comment(linker,"/STACK:124000000,124000000")#include <algorithm>#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <vector>#include <math.h>#include <queue>#include <set>#include <map>#define lson i<<1#define rson i<<1|1#define ll long long#define clr(a,b) memset(a,b,sizeof(a))#define scanfi(a) scanf("%d",&a)#define scanfs(a) scanf("%s",a)#define scanfl(a) scanf("%I64d",&a)#define scanfd(a) scanf("%lf",&a)#define key_val ch[ch[root][1]][0]#define eps 1e-7#define inf 0x3f3f3f3f3f3f3f3fusing namespace std;const ll mod = 1000000007;const int maxn = 100010;const double PI = acos(-1.0);int n;int a[maxn];struct node{ int l,r,mid; int pos,num; int Max;} tree[maxn<<2];void push_up(int i){ if(tree[lson].Max >= tree[rson].Max) { tree[i].Max= tree[lson].Max; tree[i].pos = tree[lson].pos; } else { tree[i].Max = tree[rson].Max; tree[i].pos = tree[rson].pos; } tree[i].num = tree[lson].num + tree[rson].num;}void build(int i,int l,int r){ tree[i].l = l,tree[i].r = r; tree[i].mid = (l+r) >>1; tree[i].num = 0; if(l == r && l) { tree[i].num = 1; tree[i].Max= a[l]; tree[i].pos = l; return ; } build(lson,l,tree[i].mid); build(rson,tree[i].mid+1,r); push_up(i);}int tMax,tpos;void update(int i,int k){ if(tree[i].l >= k && tree[i].r <= k) { tree[i].Max = 0; tree[i].num = 0; return ; } int mid = tree[i].mid; if(k <= mid) update(lson,k); else update(rson,k); push_up(i); return ;}void query(int i,int l,int r){ if(tree[i].l >= l && tree[i].r <= r) { if(tMax < tree[i].Max) tMax = tree[i].Max,tpos = tree[i].pos; else if(tMax == tree[i].Max) tpos = min(tree[i].pos,tpos); return ; } int mid = tree[i].mid; if(l <= mid) query(lson,l,r); if(r > mid) query(rson,l,r); push_up(i); return ;}int query_x(int i,int k){ if(tree[i].l == tree[i].r) { return tree[i].l; } int mid = tree[i].mid; if(tree[lson].num >= k) return query_x(lson,k); else return query_x(rson,k-tree[lson].num); push_up(i);}int query_num(int i,int l,int r){ if(tree[i].l >= l && tree[i].r <= r) { return tree[i].num; } int ans = 0; if(l <=tree[i].mid) ans += query_num(lson,l,r); if(r > tree[i].mid) ans += query_num(rson,l,r); return ans;}int ans[maxn];int main(){ int t;// freopen("in.txt","r",stdin); while(scanfi(n) != EOF) { scanfi(t); a[0] = 0; for(int i = 1; i <= n; i++) { scanfi(a[i]); } build(1,1,n); int cnt = 1; while(t > 0 && cnt <= n) { tMax = 0,tpos = n; if(cnt + t >= n) { query(1,1,n); update(1,tpos); t -= query_num(1,1,tpos); printf("%d\n",tMax); cnt++; a[tpos] = -1; } else { int pos = query_x(1,t+1); query(1,1,pos); update(1,tpos); t -= query_num(1,1,tpos); cnt++; printf("%d\n",tMax); a[tpos] = -1; } } for(int i = 1; i <= n; i++) if(a[i] != -1) printf("%d\n",a[i]); } return 0;}
51nod 1364 最大字典序排列(线段树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。