洛谷P4364 [九省联考2018]IIIDX 【线段树】
题目
【题目背景】
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 【线段树】的更多相关文章
- 洛谷P4364 [九省联考2018]IIIDX(线段树)
传送门 题解看得……很……迷? 因为取完一个数后,它的子树中只能取权值小于等于它的数.我们先把权值从大到小排序,然后记$a_i$为他左边(包括自己)所有取完他还能取的数的个数.那么当取完一个点$x$的 ...
- 洛谷 4364 [九省联考2018]IIIDX——“预留”的思路
题目:https://www.luogu.org/problemnew/show/P4364 原来想了一个错误的思路,就是这样: solve( cr , l , r ) 表示 cr 为根的子树填 [ ...
- 洛谷 4364 [九省联考2018]IIIDX
[题解] 一眼可以想到一个类似二叉树后序遍历的贪心做法,然而这个做法在有相同数字的情况下是错误的.最简单的反例就是n=4,d={1,1,1,2},正解是1,1,2,1,而贪心是1,1,1,2. 所以这 ...
- [BZOJ5249][九省联考2018]IIIDX(线段树)
5249: [2018多省省队联测]IIIDX Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 32 Solved: 17[Submit][Statu ...
- [九省联考2018] IIIDX 线段树+贪心
题目: 给出 k 和 n 个数,构造一个序列使得 d[i]>=d[i/k] ,并且字典序最大. 分析: 听说,当年省选的时候,这道题挡住了大批的高手,看上去十分简单,实际上那道弯段时间内是转不过 ...
- [luogu] P4364 [九省联考2018]IIIDX(贪心)
P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI ...
- 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告
P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...
- 洛谷P4363 [九省联考2018]一双木棋chess 【状压dp】
题目 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子当且仅当这个 ...
- 洛谷 P4363 [九省联考2018]一双木棋chess 题解
题目链接:https://www.luogu.org/problemnew/show/P4363 分析: 首先博弈,然后考虑棋盘的规则,因为一个子在落下时它的上面和左面都已经没有空位了,所以棋子的右下 ...
随机推荐
- JS中的作用域和作用域链
本文原链接:https://cloud.tencent.com/developer/article/1403589 前言 作用域(Scope) 1. 什么是作用域 2. 全局作用域和函数作用域 3. ...
- exportfs: /mnt/demo requires fsid= for NFS export
解决方法:/mnt/demo 10.0.1.57(fsid=0,rw,async) //加入fsid=0参数就可.
- samba修改smb.conf后,不需要重启服务,就可生效
在修改完smb.conf后,不需要重启服务.在Centos7.3与Ubuntu18.04上验证都没有问题. 猜测可能的原因:samba是在客户端进行连接时,smb服务程序读取smb.conf配置文件信 ...
- C09 指针
目录 指针相关概念 指针变量 null指针 指针的算术运算 指针数组 指向指针的指针 传递指针给函数 从函数返回指针 指针相关概念 变量 如果在程序中定义了一个变量,在对程序进行编译时,系统就会为这个 ...
- PAT (Basic Level) Practise (中文)- 1011. A+B和C (15)
http://www.patest.cn/contests/pat-b-practise/1011 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1 ...
- NSXMLParser
NSXMLParser的使用 2011-05-05 15:50:17| 分类: 解析|字号 订阅 NSXMLParser解析xml格式的数据 用法如下: 首先,NSXMLParser必须继续 ...
- vue 前端判断输入框不能输入0 空格。特殊符号。
oninput="value=value.replace(/[^\d.]/g,'').replace(/\.{2,}/g,'.').replace('.','$#$').replace(/\ ...
- 为什么要在函数内部声明 var that = this 呢
看一个例子 $('#conten').click(function(){ //this是被点击的#conten var that =this; $('.conten').each(function() ...
- STL容器之Array[转]
转自https://blog.csdn.net/sin_geek/article/details/51067874 作者 Sin_Geek 简介 array在头文件<array> 中定义 ...
- 【线段树分治 01背包】loj#6515. 「雅礼集训 2018 Day10」贪玩蓝月
考试时候怎么就是没想到线段树分治呢? 题目描述 <贪玩蓝月>是目前最火爆的网页游戏.在游戏中每个角色都有若干装备,每件装备有一个特征值 $w$ 和一个战斗力 $v$ .在每种特定的情况下, ...