System Messag 大神的题解。这个题目明显是要贪心的。从前往后每次看看能不能拿一个大的放到当前数字的前面,而且要拿尽可能大的。这样字典序才会变成最大。
原数组设为a[i]
这个过程可以用线段树来维护。先按照原数组建立线段树。树结点中记录最大值,最大值所在位置,当前区间有几个数字没有被删除。
然后从前往后开始,设当前位置为P,剩K步可以拿,那么就要从P后面拿一个a[Q],他要比a[P]大且区间[P,Q]未删除数字个数不超过K+1。可以先找到距离P最远X的且[P,X]里面未删除的数字不超过K+1个。然后查询[P,X]中最大值,如果比a[P]大就可以换了,不然的话就P++;Q放到前面之后就在线段树里面进行删除。
距离P最远X的且[P,X]里面未删除的数字不超过K+1个,这一步可以通过找[0,X]不超过某个数字来做,可以有logn.
以上步骤均可以在logn以内实现,所以总复杂度是nlogn。
#include <iostream> #include <stdio.h> #include <map> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; template<class T> void read(T & x) { char ch = getchar(); bool sign = false; x = 0; while (ch < '0' || ch > '9') { if (ch == '-') sign = true; ch = getchar(); } while ('0' <= ch && ch <= '9') { x = 10 * x + ch - '0'; ch = getchar(); } if (sign) x = -x; } template<class T> void print(T x) { if (x > 9) print(x / 10); putchar('0' + (x % 10)); } template<class T> void println(T x) { print(x); puts(""); } template<class T> inline T sqr(T a) { return a * a; } //============================================= const int N = 1e5 + 5; #define ls u << 1 #define rs u << 1 | 1 #define mid ((l + r) >> 1) #define lson u << 1,l,mid #define rson u << 1 | 1,mid + 1,r typedef pair<int,int> PAIR; struct Tree { int Max[N << 2],num[N << 2],id[N << 2]; void pushup(int u) { num[u] = num[ls] + num[rs]; int tp = (Max[ls] < Max[rs] ? rs : ls); Max[u] = Max[tp]; id[u] = id[tp]; } void build(int u,int l,int r) { if(l == r) { scanf("%d",Max + u); num[u] = 1; id[u] = l; } else { build(lson); build(rson); pushup(u); } } void Delete(int u,int l,int r,int x) { if(l == r) { Max[u] = num[u] = id[u] = 0; } else { if(x <= mid) Delete(lson,x); else Delete(rson,x); pushup(u); } } PAIR QueMaxId(int u,int l,int r,int x,int y) { if(x <= l && y >= r) { return make_pair(Max[u],id[u]); } else { PAIR tp,ans = make_pair(0,0); if(x <= mid) { tp = QueMaxId(lson,x,y); if(tp.first > ans.first) ans = tp; } if(y > mid) { tp = QueMaxId(rson,x,y); if(tp.first > ans.first) ans = tp; } return ans; } } int que_num(int u,int l,int r,int x,int y) { if(x <= l && y >= r) { return num[u]; } else { int tp = 0; if(x <= mid) tp += que_num(lson,x,y); if(y > mid) tp += que_num(rson,x,y); return tp; } } int que(int u,int l,int r,int x,int k) { if(l == r) { return l; } else { if(k <= num[ls]) return que(lson,x,k); else return que(rson,x,k - num[ls]); } } }ac; int main() { int n,k,num = 0; read(n); read(k); ac.build(1,1,n); for(int i = 1; num < n; i++) { int id = ac.que(1,1,n,n,k + 1); PAIR tmp = ac.QueMaxId(1,1,n,i,id); printf("%d\n",tmp.first); ac.Delete(1,1,n,tmp.second); k -= ac.que_num(1,1,n,1,tmp.second); if(tmp.second != i) i--; num++; } }