题目

【题目背景】

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。那假如是你,你会怎么解决这份任务呢

输入格式

第1行1个正整数n和1个小数k,n表示曲目数量,k其含义如题所示。

第2行n个用空格隔开的正整数d,表示这n首曲目的难度。

1 ≤ n ≤ 500000

1 < k ≤ 10^9

1 < d ≤ 10^9

输出格式

输出1行n个整数,按顺序输出安排完曲目顺序后第i首曲目的难度。

若有多解,则输出d1最大的;若仍有多解,则输出d2最大的,以此类推。

输入样例

4 2.0

114 514 1919 810

输出样例

114 810 514 1919

题解

太神了,,orz

有一个很明显的错误贪心就不多说了

直接讲正解

将权值降序排序

建立一个线段树维护一个数组\(pre[i]\),表示\(i\)号权值之前有几个位置可选,初始化\(pre[i] = i\)

我们从\(1\)号点顺序访问每个点,在线段树上二分查找右侧\(pre[]\)都大于\(siz[u]\)的位置,然后找到该位置的最右相同权值的位置\(pos\),赋给当前点

然后我们为了给其子树留够\(siz[u] - 1\)个值【同时减去已经用掉的一个值】,我们将区间\([pos,n]\)减去\(siz[u]\),这样就保证了外面的点选完之后一定会给子树内的点留够那么多之前的权值

我们访问到一个点时,如果该点有父亲,那么要撤销掉父亲的预留操作【但多个儿子只撤销一次】

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
double K;
int n,siz[maxn],cnt[maxn],fa[maxn],val[maxn],rel[maxn],ans[maxn];
int mn[maxn << 2],tag[maxn << 2];
void upd(int u){mn[u] = min(mn[ls],mn[rs]);}
void pd(int u){
if (tag[u] != 0){
mn[ls] += tag[u]; tag[ls] += tag[u];
mn[rs] += tag[u]; tag[rs] += tag[u];
tag[u] = 0;
}
}
void build(int u,int l,int r){
if (l == r){
mn[u] = l;
return;
}
int mid = l + r >> 1;
build(ls,l,mid);
build(rs,mid + 1,r);
upd(u);
}
void modify(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R) {
mn[u] += v; tag[u] += v;
return;
}
pd(u);
int mid = l + r >> 1;
if (mid >= L) modify(ls,l,mid,L,R,v);
if (mid < R) modify(rs,mid + 1,r,L,R,v);
upd(u);
}
int query(int u,int l,int r,int v){
if (l == r) return mn[u] >= v ? l : l + 1;
pd(u);
int mid = l + r >> 1;
if (mn[rs] >= v) return query(ls,l,mid,v);
return query(rs,mid + 1,r,v);
}
inline bool cmp(const int& a,const int& b){
return a > b;
}
int main(){
n = read(); scanf("%lf",&K);
REP(i,n) val[i] = read();
REP(i,n) fa[i] = (int)floor(i / K);
for (int i = n; i; i--){
siz[i]++;
siz[fa[i]] += siz[i];
}
sort(val + 1,val + 1 + n,cmp);
for (int i = n; i; i--){
if (i == n || val[i] != val[i + 1]) cnt[i] = 1;
else cnt[i] = cnt[i + 1] + 1;
}
build(1,1,n);
for (int i = 1; i <= n; i++){
if (fa[i] && !rel[fa[i]]){
rel[fa[i]] = true;
modify(1,1,n,ans[fa[i]],n,siz[fa[i]] - 1);
}
int p = query(1,1,n,siz[i]),u;
u = p + cnt[p] - 1; cnt[p]--;
ans[i] = u;
modify(1,1,n,u,n,-siz[i]);
}
REP(i,n) printf("%d ",val[ans[i]]);
return 0;
}

洛谷P4364 [九省联考2018]IIIDX 【线段树】的更多相关文章

  1. 洛谷P4364 [九省联考2018]IIIDX(线段树)

    传送门 题解看得……很……迷? 因为取完一个数后,它的子树中只能取权值小于等于它的数.我们先把权值从大到小排序,然后记$a_i$为他左边(包括自己)所有取完他还能取的数的个数.那么当取完一个点$x$的 ...

  2. 洛谷 4364 [九省联考2018]IIIDX——“预留”的思路

    题目:https://www.luogu.org/problemnew/show/P4364 原来想了一个错误的思路,就是这样: solve( cr , l , r ) 表示 cr 为根的子树填 [ ...

  3. 洛谷 4364 [九省联考2018]IIIDX

    [题解] 一眼可以想到一个类似二叉树后序遍历的贪心做法,然而这个做法在有相同数字的情况下是错误的.最简单的反例就是n=4,d={1,1,1,2},正解是1,1,2,1,而贪心是1,1,1,2. 所以这 ...

  4. [BZOJ5249][九省联考2018]IIIDX(线段树)

    5249: [2018多省省队联测]IIIDX Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 32  Solved: 17[Submit][Statu ...

  5. [九省联考2018] IIIDX 线段树+贪心

    题目: 给出 k 和 n 个数,构造一个序列使得 d[i]>=d[i/k] ,并且字典序最大. 分析: 听说,当年省选的时候,这道题挡住了大批的高手,看上去十分简单,实际上那道弯段时间内是转不过 ...

  6. [luogu] P4364 [九省联考2018]IIIDX(贪心)

    P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI ...

  7. 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告

    P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...

  8. 洛谷P4363 [九省联考2018]一双木棋chess 【状压dp】

    题目 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子当且仅当这个 ...

  9. 洛谷 P4363 [九省联考2018]一双木棋chess 题解

    题目链接:https://www.luogu.org/problemnew/show/P4363 分析: 首先博弈,然后考虑棋盘的规则,因为一个子在落下时它的上面和左面都已经没有空位了,所以棋子的右下 ...

随机推荐

  1. codeforce Gym 100418K Cards (概率,数学)

    题意:麦田的故事,n张牌,取x张牌,记住前x张牌最大的值m,继续往后取,遇到第一张比m大的牌就停下来.求一个x使得最后的牌在整副牌里是最大的期望最大. 假设最大的牌是A,A在各种位置出现的概率就是相等 ...

  2. event loop、进程和线程、任务队列

    本文原链接:https://cloud.tencent.com/developer/article/1106531 https://cloud.tencent.com/developer/articl ...

  3. NBear简介与使用图解

    NBear简介与使用图解 框架类型:ORM映射框架 简介:NBear是一个基于.Net 2.0.C#2.0开放全部源代码的的软件开发框架类库.NBear的设计目标是尽最大努力减少开发人员的工作量,最大 ...

  4. setTimeout,clearTimeout的一些好用法

    if(hidden != 1){ $.ui.showMask(); var _aaa = setTimeout(function(){ $.ui.hideMask(); },5000); } //be ...

  5. c++作业:输入两个整数,用函数求两数之和。函数外部声明有什么作用?

    #include <iostream> using namespace std; int main(){ //求两数的和? int a,b,s; cout<<"请你输 ...

  6. VS连接SQL Server 2008,并实现登录和注册功能

    --------------------- 作者:Cambridge 来源:CSDN 原文:https://blog.csdn.net/cambridgeacm/article/details/797 ...

  7. ANSI C 与 K&R C

    C语言由Dennis M.Ritchie在1973年设计和实现.从那以后使用者逐渐增加.到1978年Ritchie和Bell实验室的另一位程序专家Kernighan合写了著名的<TheC Pro ...

  8. 【wqs二分】HHHOJ#15. 赤

    这个wqs二分并不熟练…… 题目描述 #15. 赤 题目分析 两维都用wqs二分,其他没有什么特殊之处. 重点在于,wqs二分还原最优解的时候,增量是强制给的k. #include<bits/s ...

  9. 201621123080《Java程序设计》第三周学习总结

    Week03-面向对象入门 1. 本周学习总结 2. 书面作业 1.以面向对象方式改造数据结构作业'有理数'(重点) 1.1 截图你主要代码(需要在程序中出现你的学号和姓名)并粘贴程序的git地址. ...

  10. http客户端与浏览器的区别

    两者区别:浏览器对http响应头会进行特定处理(如自动读取本地缓存.设置cookie等),而http客户端(如crul)可能没有像浏览器那样的处理,某些封装程度高的http客户端,可能会有. 同一个文 ...