5249: [2018多省省队联测]IIIDX
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 499 Solved: 236
[ Submit][ Status][ Discuss]
Description
【题目背景】
Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏。现在
,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了。这款音乐游戏内一般都包含了许多歌曲,歌曲
越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲
目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。
【题目描述】
这一天,Konano接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目的解锁顺序。游戏内共有n首曲目
,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第trunc(i/k)首曲目后解锁(x为下取整符号)若tru
nc(i/k)=0,则说明这首曲目无需解锁。举个例子:当k=2时,第1首曲目是无需解锁的(trunc(1/2)=0),第7首曲
目需要玩家Pass第trunc(7/2)=3首曲目才会被解锁。Konano的工作,便是安排这些曲目的顺序,使得每次解锁出的
曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i满足Di≥Dtrun
c(i/k)。当然这难不倒曾经在信息学竞赛摸鱼许久的Konano。那假如是你,你会怎么解决这份任务呢
Input
第1行1个正整数n和1个小数k,n表示曲目数量,k其含义如题所示。
第2行n个用空格隔开的正整数d,表示这n首曲目的难度。
1 ≤ n ≤ 500000
1 < k ≤ 10^9
1 < d ≤ 10^9
Output
输出1行n个整数,按顺序输出安排完曲目顺序后第i首曲目的难度。
若有多解,则输出d1最大的;若仍有多解,则输出d2最大的,以此类推。
Sample Input
4 2.0
114 514 1919 810
114 514 1919 810
Sample Output
114 810 514 1919
HINT
Source
#include<queue> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> using namespace std; typedef long long LL; typedef double DL; const int INF = 2147483647; const int maxn = 500010; const int segn = 4 * maxn; const DL eps = 1e-5; DL k; vector<int> e[maxn]; int n,a[maxn]; int fr[maxn],siz[maxn],fa[maxn],used[maxn]; int data[maxn],cnt[maxn],N; int minx[segn],set[segn]; inline LL getint() { LL ret = 0,f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar(); return ret * f; } inline void add(int o,int x) { minx[o] += x; set[o] += x; } inline void pushdown(int o) { if (set[o]) { int lc = o << 1,rc = o << 1 | 1; add(lc,set[o]); add(rc,set[o]); set[o] = 0; } } inline void maintain(int o) { int lc = o << 1,rc = o << 1 | 1; minx[o] = min(minx[lc],minx[rc]); } inline void modify(int o,int l,int r,int al,int ar,int x) { if (al > ar) return; if (al <= l && r <= ar) {add(o,x); return;} pushdown(o); int lc = o << 1,rc = o << 1 | 1,mid = l + r >> 1; if (al <= mid) modify(lc,l,mid,al,ar,x); if (mid < ar) modify(rc,mid + 1,r,al,ar,x); maintain(o); } inline int Query(int o,int l,int r,int x) { if (l == r) return minx[o] >= x ? l : l - 1; pushdown(o); int mid = l + r >> 1,lc = o << 1,rc = o << 1 | 1; if (minx[lc] >= x) return Query(rc,mid + 1,r,x); else return Query(lc,l,mid,x); } inline void build(int o,int l,int r) { if (l == r) {minx[o] = n - l + 1; return;} int mid = l + r >> 1,lc = o << 1,rc = o << 1 | 1; build(lc,l,mid); build(rc,mid + 1,r); maintain(o); } inline void dfs(int u) { siz[u] = 1; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i]; dfs(v); siz[u] += siz[v]; } } inline void print(int x) { if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } inline int equ(DL x,DL y) { return fabs(x - y) <= eps; } int main() { n = getint(); scanf("%lf",&k); for (int i = 1; i <= n; i++) a[i] = getint(); sort(a + 1,a + n + 1); for (int i = 1; i <= n; i++) { if (i == 1 || a[i] != a[i - 1]) cnt[i] = 0; else cnt[i] = cnt[i - 1] + 1; } for (int i = 1; i <= n; i++) { fa[i] = equ(floor(i / k) + 1,i / k) ? floor(i / k) + 1 : floor(i / k); e[fa[i]].push_back(i); } dfs(0); build(1,1,n); for (int i = 0; i <= n; i++) { if (!used[fa[i]] && fa[i]) { used[fa[i]] = 1; modify(1,1,n,1,fr[fa[i]],siz[fa[i]] - 1); } if (i) { int tmp = Query(1,1,n,siz[i]); tmp -= cnt[tmp]; fr[i] = tmp + cnt[tmp]; cnt[tmp]++; modify(1,1,n,1,fr[i],-siz[i]); } } for (int i = 1; i <= n; i++) print(a[fr[i]]) , putchar(' '); return 0; }