[luogu] P4364 [九省联考2018]IIIDX(贪心)
P4364 [九省联考2018]IIIDX
题目背景
Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏。现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了。
这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。
题目描述
这一天,Konano 接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目 的解锁顺序。游戏内共有n 首曲目,每首曲目都会有一个难度d,游戏内第i 首曲目会在玩家Pass 第\(\lfloor \frac{i}{k} \rfloor\) 首曲目后解锁(\(\lfloor x \rfloor\) 为下取整符号)若\(\lfloor \frac{i}{k} \rfloor = 0\),则说明这首曲目无需解锁
举个例子:当k = 2 时,第1 首曲目是无需解锁的(\(\lfloor \frac{1}{2} \rfloor = 0\)),第7 首曲目需要玩家Pass 第\(\lfloor \frac{7}{2} \rfloor = 3\) 首曲目才会被解锁。
Konano 的工作,便是安排这些曲目的顺序,使得每次解锁出的曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i 满足
\(d_i \geq d_{\lfloor \frac{i}{k} \rfloor}\)
当然这难不倒曾经在信息学竞赛摸鱼许久的Konano。那假如是你,你会怎么解决这份任务呢?
输入输出格式
输入格式:
第1 行1 个正整数n 和1 个小数k,n 表示曲目数量,k 其含义如题所示。
第2 行n 个用空格隔开的正整数d,表示这n 首曲目的难度。
输出格式:
输出到文件iiidx.out 中。
输出1 行n 个整数,按顺序输出安排完曲目顺序后第i 首曲目的难度。
若有多解,则输出d1 最大的;若仍有多解,则输出d2最大的,以此类推。
输入输出样例
输入样例#1: 复制
4 2.0
114 514 1919 810
输出样例#1: 复制
114 810 514 1919
说明

题解
做个人不好吗。。
本题有一个55分的贪心,可以过60分
就是直接按题意暴力建树然后贪心,能赋大值就赋大值。
树的边就是按\(\lfloor \frac{i}{k} \rfloor\)来的。
事实上这个贪心是不能解决多个\(d_i\)相同的。
如
input
4 2.0
1 1 1 2
output
1 1 2 1
错误答案
1 1 1 2
即在建树过程中,(图片来自NaVi_Awson)

当2节点和4节点可以取相同值,且3独立时,我们应该是优先,2,4为1,3为2的,但是贪心一定会把2赋值给4节点。
我们维护一个数组\(f[i]\),表示\(i\)节点之前还有剩余的点数。
从大到小排序,然后我们找优先靠左的满足\(f[i]>=size[x]\)的数字。
\(size[x]\)表示答案序列第\(x\)位的子树大小。
然后维护一个\(nxt[]\)数组,表示相同的数值时优先选靠右的。
然后第\(i\)到\(n\)位的\(f[]-size[x]\);
这样可以解决掉那个重复的带来的影响。
两个循环暴力找和减去是\(O(n^2)\)
转移到线段树上就可以了\(O(nlogn)\)
我之前一直不明白为什么如果当前点有父亲,要重新加上父亲的预留值。
Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+5;
int sum[N<<2],lazy[N<<2];
int a[N],n,ans[N],size[N],fa[N],nxt[N];
double k;
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
void build(int root,int left,int right){
int mid=(left+right)>>1;
if(left==right){
sum[root]=left;return ;
}build(root<<1,left,mid);build(root<<1|1,mid+1,right);
sum[root]=min(sum[root<<1],sum[root<<1|1]);
}
void push(int root,int left,int right){
sum[root<<1]+=lazy[root];sum[root<<1|1]+=lazy[root];
lazy[root<<1]+=lazy[root];lazy[root<<1|1]+=lazy[root];
lazy[root]=0;
}
void update(int root,int left,int right,int l,int r,int v){
if(left>r||right<l)return ;
if(lazy[root])push(root,left,right);
if(left>=l&&right<=r){
sum[root]+=v;lazy[root]+=v;
return ;
}int mid=(left+right)>>1;
if(mid>=l) update(root<<1,left,mid,l,r,v);
if(mid<r) update(root<<1|1,mid+1,right,l,r,v);
sum[root]=min(sum[root<<1],sum[root<<1|1]);
}
int query(int root,int left,int right,int k){
if(left==right){
return sum[root]>=k?left:left+1;
}int mid=(left+right)>>1;
if(lazy[root])push(root,left,right);
if(sum[root<<1|1]>=k) return query(root<<1,left,mid,k);
else return query(root<<1|1,mid+1,right,k);
}
bool cmp(int a,int b){return a>b;}
int main(){
n=read();cin>>k;
for(int i=1;i<=n;i++)a[i]=read();sort(a+1,a+n+1,cmp);
for(int i=n;i>=1;i--){
nxt[i]=i;fa[i]=(1.0*i/k);
size[i]++;size[fa[i]]+=size[i];
if(a[i]==a[i+1])nxt[i]=nxt[i+1];
}build(1,1,n);
for(int i=1;i<=n;i++){
if(fa[i]&&fa[i]!=fa[i-1])update(1,1,n,ans[fa[i]],n,size[fa[i]]-1);
int tmp=nxt[query(1,1,n,size[i])];ans[i]=tmp;
update(1,1,n,tmp,n,-size[i]);
}
for(int i=1;i<=n;i++)cout<<a[ans[i]]<<' ';
return 0;
}
P4364 [九省联考2018]IIIDX
题目背景
Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏。现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了。
这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。
题目描述
这一天,Konano 接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目 的解锁顺序。游戏内共有n 首曲目,每首曲目都会有一个难度d,游戏内第i 首曲目会在玩家Pass 第\lfloor \frac{i}{k} \rfloor⌊
k
i
⌋ 首曲目后解锁(\lfloor x \rfloor⌊x⌋ 为下取整符号)若\lfloor \frac{i}{k} \rfloor = 0⌊
k
i
⌋=0,则说明这首曲目无需解锁
举个例子:当k = 2 时,第1 首曲目是无需解锁的(\lfloor \frac{1}{2} \rfloor = 0⌊
2
1
⌋=0),第7 首曲目需要玩家Pass 第\lfloor \frac{7}{2} \rfloor = 3⌊
2
7
⌋=3 首曲目才会被解锁。
Konano 的工作,便是安排这些曲目的顺序,使得每次解锁出的曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i 满足
d_i \geq d_{\lfloor \frac{i}{k} \rfloor}d
i
≥d
⌊
k
i
⌋
当然这难不倒曾经在信息学竞赛摸鱼许久的Konano。那假如是你,你会怎么解决这份任务呢?
输入输出格式
输入格式:
第1 行1 个正整数n 和1 个小数k,n 表示曲目数量,k 其含义如题所示。
第2 行n 个用空格隔开的正整数d,表示这n 首曲目的难度。
输出格式:
输出到文件iiidx.out 中。
输出1 行n 个整数,按顺序输出安排完曲目顺序后第i 首曲目的难度。
若有多解,则输出d1 最大的;若仍有多解,则输出d2最大的,以此类推。
输入输出样例
输入样例#1: 复制
4 2.0
114 514 1919 810
输出样例#1: 复制
114 810 514 1919
说明
题解
做个人不好吗。。
本题有一个55分的贪心,可以过60分
就是直接按题意暴力建树然后贪心,能赋大值就赋大值。
树的边就是按\lfloor \frac{i}{k} \rfloor⌊
k
i
⌋来的。
事实上这个贪心是不能解决多个d_id
i
相同的。
如
input
4 2.0
1 1 1 2
output
1 1 2 1
错误答案
1 1 1 2
即在建树过程中,(图片来自NaVi_Awson)
当2节点和4节点可以取相同值,且3独立时,我们应该是优先,2,4为1,3为2的,但是贪心一定会把2赋值给4节点。
我们维护一个数组f[i]f[i],表示ii节点之前还有剩余的点数。
从大到小排序,然后我们找优先靠左的满足f[i]>=size[x]f[i]>=size[x]的数字。
size[x]size[x]表示答案序列第xx位的子树大小。
然后维护一个nxt[]nxt[]数组,表示相同的数值时优先选靠右的。
然后第ii到nn位的f[]-size[x]f[]−size[x];
这样可以解决掉那个重复的带来的影响。
两个循环暴力找和减去是O(n^2)O(n
2
)
转移到线段树上就可以了O(nlogn)O(nlogn)
我之前一直不明白为什么如果当前点有父亲,要重新加上父亲的预留值。
Code
include
include
include
include
include
using namespace std;
const int N=1e6+5;
int sum[N<<2],lazy[N<<2];
int a[N],n,ans[N],size[N],fa[N],nxt[N];
double k;
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x10+ch-'0',ch=getchar();
return xw;
}
void build(int root,int left,int right){
int mid=(left+right)>>1;
if(left==right){
sum[root]=left;return ;
}build(root<<1,left,mid);build(root<<1|1,mid+1,right);
sum[root]=min(sum[root<<1],sum[root<<1|1]);
}
void push(int root,int left,int right){
sum[root<<1]+=lazy[root];sum[root<<1|1]+=lazy[root];
lazy[root<<1]+=lazy[root];lazy[root<<1|1]+=lazy[root];
lazy[root]=0;
}
void update(int root,int left,int right,int l,int r,int v){
if(left>r||right<l)return ;
if(lazy[root])push(root,left,right);
if(left>=l&&right<=r){
sum[root]+=v;lazy[root]+=v;
return ;
}int mid=(left+right)>>1;
if(mid>=l) update(root<<1,left,mid,l,r,v);
if(mid<r) update(root<<1|1,mid+1,right,l,r,v);
sum[root]=min(sum[root<<1],sum[root<<1|1]);
}
int query(int root,int left,int right,int k){
if(left==right){
return sum[root]>=k?left:left+1;
}int mid=(left+right)>>1;
if(lazy[root])push(root,left,right);
if(sum[root<<1|1]>=k) return query(root<<1,left,mid,k);
else return query(root<<1|1,mid+1,right,k);
}
bool cmp(int a,int b){return a>b;}
int main(){
n=read();cin>>k;
for(int i=1;i<=n;i++)a[i]=read();sort(a+1,a+n+1,cmp);
for(int i=n;i>=1;i--){
nxt[i]=i;fa[i]=(1.0*i/k);
size[i]++;size[fa[i]]+=size[i];
if(a[i]==a[i+1])nxt[i]=nxt[i+1];
}build(1,1,n);
for(int i=1;i<=n;i++){
if(fa[i]&&fa[i]!=fa[i-1])update(1,1,n,ans[fa[i]],n,size[fa[i]]-1);
int tmp=nxt[query(1,1,n,size[i])];ans[i]=tmp;
update(1,1,n,tmp,n,-size[i]);
}
for(int i=1;i<=n;i++)cout<<a[ans[i]]<<' ';
return 0;
}
Markdown selection 21 bytes 2 words 0 lines Ln 1, Col 23 HTML 3224 characters 246 words 115 paragraphs
[luogu] P4364 [九省联考2018]IIIDX(贪心)的更多相关文章
- [luogu]P4364 [九省联考2018]IIIDX
题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了. 这款音乐 ...
- 洛谷P4364 [九省联考2018]IIIDX 【线段树】
题目 [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在 ,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了.这款 ...
- p4364 [九省联考2018]IIIDX
传送门 分析 我们先考虑如果所有数都不相同我们应该怎么办 我们可以直接贪心的在每个点放可行的最大权值 但是题目要求可以有相同的数 我们可以考虑每次让当前节点可发且尽量大的同时给兄弟节点留的数尽量大 我 ...
- 洛谷P4364 [九省联考2018]IIIDX(线段树)
传送门 题解看得……很……迷? 因为取完一个数后,它的子树中只能取权值小于等于它的数.我们先把权值从大到小排序,然后记$a_i$为他左边(包括自己)所有取完他还能取的数的个数.那么当取完一个点$x$的 ...
- BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)
BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...
- [九省联考2018]IIIDX 贪心 线段树
~~~题面~~~ 题解: 一开始翻网上题解看了好久都没看懂,感觉很多人都讲得不太详细,所以导致一些细节的地方看不懂,所以这里就写详细一点吧,如果有不对的or不懂的可以发评论在下面. 首先有一个比较明显 ...
- 洛谷 4364 [九省联考2018]IIIDX——“预留”的思路
题目:https://www.luogu.org/problemnew/show/P4364 原来想了一个错误的思路,就是这样: solve( cr , l , r ) 表示 cr 为根的子树填 [ ...
- BZOJ5249:[九省联考2018]IIIDX——题解
https://www.luogu.org/problemnew/show/P4364#sub https://www.lydsy.com/JudgeOnline/problem.php?id=524 ...
- [BZOJ5249][九省联考2018]IIIDX(线段树)
5249: [2018多省省队联测]IIIDX Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 32 Solved: 17[Submit][Statu ...
随机推荐
- 工具-VS CODE快捷键
快捷键 Ctrl+P 通过文件名或者标签名导航 Ctrl+Tab 在前一个文件和当前文件间切换 F1 打开全局命令 Ctrl+Shift+O will let you navigate ...
- Android获取图片实际大小兼容平板电脑
项目中有个图片在平板电脑中显示特别小的原因.一直苦于没找到原因,也没有平板电脑測试,今天找了个改动分辨率的,编写相关方法最终处理了,记录下比較: 好让以后不造轮子. 主要是获取文章相关图片显示问题.直 ...
- linux入门基础——linux用户基础
这篇内容是linux用户基础,相关内容见linux改动username和ubuntu改动username和主机名. 用户.组 当我们使用linux时,须要以一个用户的身份登入,一个进程也须要以一个用户 ...
- string转utf8后解决TTS识别中文的问题
今天遇到string字符编码的问题,由于遇到了用TTS将文本转语音的一个API,里面的中文必须是utf8的,我传了一个uncode编码的中文进去,就一直不能正常读出来.后来才发现是编码的问题.这里在网 ...
- 金蝶KIS标准版与金蝶K3的差别
一.数据库 金蝶KIS标准版使用MS Access数据库.该数据库适用于小规模的数据处理,是比較经济的数据库解决方式,但当单个表的数据记录超过5万条时.执行的速度和稳定性都将受到一定程序的影响. K ...
- Codeforces Beta Round #29 (Div. 2, Codeforces format) C. Mail Stamps 拓扑排序
C. Mail Stamps One day Bob got a letter in an envelope. Bob knows that when Berland's post offic ...
- Linux less命令简介
less命令可以对文件或其它输出进行分页显示,与moe命令相似,但是比more命令要强大许多. 在 less 中导航命令类似于 vi,如下: 1 搜索 当使用命令 less file-name 打开一 ...
- weblogic管理脚本
start.sh Java代码 #!/usr/bin/bash # # start.sh # @auth: zhoulin@lianchuang.com # SERVER_STATUS () { s ...
- 信息安全-加密:SM4.0
ylbtech-信息安全-加密:SM4.0 SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布.相关标准为“GM/T 0002-201 ...
- 用户命令切换-命令su
命令su格式为su [-] username su su - su test su root