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;
}