[BZOJ5249][九省联考2018]IIIDX(线段树)
2018-04-08 08:06
363 查看
5249: [2018多省省队联测]IIIDX
Time Limit: 40 Sec Memory Limit: 512 MB
Submit: 32 Solved: 17
[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^9Output
输出1行n个整数,按顺序输出安排完曲目顺序后第i首曲目的难度。 若有多解,则输出d1最大的;若仍有多解,则输出d2最大的,以此类推。Sample Input
4 2.0
114 514 1919 810
Sample Output
114 810 514 1919HINT
Source
[Submit][Status][Discuss]
首先有一个显然的贪心,把树建出来然后后序遍历从大到小填数即可。
但是这样在有重复数字的情况下是不行的,如:
4 2
1 1 1 2
这样贪心答案是1 1 1 2,但正确答案是1 1 2 1。
这就需要对每个数进行“预订”操作。考虑将数从小到大填进树里,显然当前可能填进的节点一定与已经填过的节点相邻,所以我们把这些节点子树都“预订”好,然后找到最靠后的,且不造成上面那个错误的节点填入,最终整棵树就填好了。
具体实现很难讲清楚,还是看代码吧。
#include <cmath> #include <cstdio> #include <algorithm> #define N 500010 #define lson l ,mid ,x << 1 #define rson mid + 1 ,r ,x << 1 | 1 #define rep(i,l,r) for (int i=l; i<=r; i++) using namespace std; int a ,ans ,head ,to ,nxt ,cnt ,si ,sum[N << 2]; void add(int x ,int y){ to[++cnt] = y ,nxt[cnt] = head[x] ,head[x] = cnt ,si[x] += si[y]; } void update(int p ,int a ,int l ,int r ,int x){ sum[x] += a; if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) update(p ,a ,lson); else update(p ,a ,rson); } int find(int k ,int l ,int r ,int x){ if(l == r) return l; int mid = (l + r) >> 1; if(sum[x << 1 | 1] < k) return find(k - sum[x << 1 | 1] ,lson); else return find(k ,rson); } int main(){ int n ,i ,j ,t ,l ,last = 1; double k; scanf("%d%lf" ,&n ,&k); rep(i,1,n) scanf("%d" ,&a[i]) ,si[i] = 1; sort(a + 1 ,a + n + 1); for(i = n ; i ; i -- ) add((int)floor(i / k) ,i); for(i = head[0] ; i ; i = nxt[i]) update(to[i] ,si[to[i]] ,1 ,n ,1); for(i = 1 ; i <= n ; i = last){ while(last <= n && a[i] == a[last]) last ++ ; for(j = last - i ; j ; j -- ){ t = find(j ,1 ,n ,1) ,ans[t] = a[i] ,update(t ,-si[t] ,1 ,n ,1); for(l = head[t] ; l ; l = nxt[l]) update(to[l] ,si[to[l]] ,1 ,n ,1); } } rep(i,1,n) printf("%d " ,ans[i]); return 0; }
相关文章推荐
- BZOJ_5249_Luogu_P4364_[2018多省省队联测]_IIIDX_九省联考2018_JLOI2018_线段树
- 洛谷P4364 [九省联考2018]IIIDX 【线段树】
- BZOJ5249 九省联考2018IIIDX(线段树+贪心)
- [BZOJ5249][多省联测2018]IIIDX
- BZOJ.5248.[九省联考2018]一双木棋chess(对抗搜索 记忆化)
- [九省联考 2018]IIIDX
- [BZOJ4869][六省联考2017]相逢是问候(线段树+扩展欧拉定理)
- [BZOJ5286][HNOI2018]转盘(线段树)
- [BZOJ5248][九省联考2018]一双木棋(连通性DP,对抗搜索)
- [BZOJ5250][九省联考2018]秘密袭击(DP)
- BZOJ5249: [2018多省省队联测]IIIDX
- [BZOJ5286][洛谷P4425][HNOI2018]转盘(线段树)
- 【BZOJ5251】【八省联考2018】劈配(网络流,二分答案)
- 【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)
- [九省联考2018]IIIDX
- [BZOJ5251][九省联考2018]劈配(网络流)
- BZOJ 1858: [Scoi2010]序列操作 [线段树]
- bzoj 3747 [POI2015]Kinoman 线段树
- BZOJ 题目3211: 花神游历各国(线段树区间减为平方根,区间求和)
- 【线段树】BZOJ2989 数列