https://www.luogu.org/problemnew/show/P4364#sub

https://www.lydsy.com/JudgeOnline/problem.php?id=5249

Konano接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目的解锁顺序。游戏内共有n首曲目,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第trunc(i/k)首曲目后解锁(x为下取整符号)若trunc(i/k)=0,则说明这首曲目无需解锁。举个例子:当k=2时,第1首曲目是无需解锁的(trunc(1/2)=0),第7首曲目需要玩家Pass第trunc(7/2)=3首曲目才会被解锁。Konano的工作,便是安排这些曲目的顺序,使得每次解锁出的曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i满足Di≥Dtrunc(i/k)。

智商好题。

当时在考场上就写的55分贪心,之后也举出过反例证明无法贪掉d有重复的点,结果凉凉。

但其实和贪心差不多,我们先对d从大到小排序,则对于每个靠前的点来说,它在合法态下尽可能取最靠左的d,而当d相同时它尽可能靠右。

这个位置可以用二分得到,至于合法就用线段树维护当前点左边还可以取多少点即可。

PS:bzoj卡精度。

#include<cstdio>
#include<cmath>
#include<vector>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef double dl;
const int N=5e5+;
const int INF=1e9;
const dl eps=1e-;
inline int read(){
int x=,w=;char ch=;
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*w;
}
int n,d[N],tr[N*],lz[N*],cnt[N],size[N],fa[N],ans[N];
dl k;
inline bool cmp(int a,int b){return a>b;}
inline void upt(int a){tr[a]=min(tr[a<<],tr[a<<|]);}
inline void push(int a){
if(!lz[a])return;
lz[a<<]+=lz[a];lz[a<<|]+=lz[a];
tr[a<<]+=lz[a];tr[a<<|]+=lz[a];
lz[a]=;
}
void build(int a,int l,int r){
if(l==r){
tr[a]=l;
return;
}
int mid=(l+r)>>;
build(a<<,l,mid);build(a<<|,mid+,r);
upt(a);
}
void mdy(int a,int l,int r,int l1,int r1,int w){
if(r<l1||r1<l)return;
if(l1<=l&&r<=r1){
tr[a]+=w;lz[a]+=w;
return;
}
push(a);
int mid=(l+r)>>;
mdy(a<<,l,mid,l1,r1,w);mdy(a<<|,mid+,r,l1,r1,w);
upt(a);
}
int query(int a,int l,int r,int x){
if(l==r)return tr[a]>=x?l:l+;
push(a);
int mid=(l+r)>>;
if(x>tr[a<<|])return query(a<<|,mid+,r,x);
return query(a<<,l,mid,x);
}
int main(){
scanf("%d%lf",&n,&k);
for(int i=;i<=n;i++)d[i]=read();
sort(d+,d+n+,cmp);
for(int i=n;i>=;i--){
if(d[i]==d[i+])cnt[i]=cnt[i+]+;
else cnt[i]=;
fa[i]=(int)((dl)i/k+eps);size[i]++;
size[fa[i]]+=size[i];
}
build(,,n);
for(int i=;i<=n;i++){
if(fa[i]&&fa[i]!=fa[i-]){
mdy(,,n,ans[fa[i]],n,size[fa[i]]-);
}
int x=query(,,n,size[i]);
int t=x;x+=cnt[x];cnt[t]--;
ans[i]=x;
mdy(,,n,ans[i],n,-size[i]);
}
for(int i=;i<=n;i++)printf("%d ",d[ans[i]]);
puts("");
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

最新文章

  1. 为什么Smalltalk不流行
  2. 页面置换算法 - FIFO、LFU、LRU
  3. 【CodeVS 3160】最长公共子串
  4. 【树莓派】使用树莓派制作img镜像(二)
  5. URL的格式scheme
  6. CSS3美化表单 移动端可用
  7. [转] 使用Spring Boot和Gradle创建项目
  8. 如果ie6跳转
  9. openStack 王者归来之 trivial matters
  10. HDU1492/The number of divisors(约数) about Humble Numbers
  11. cvim常用快捷键
  12. 微信小程序简单入门理解
  13. Python之数据结构基础
  14. List,Set,Map
  15. webpack4: compilation.mainTemplate.applyPluginsWaterfall is not a function 解决方法
  16. FreeSql.DbContext 第二个版本介绍
  17. Windows中通过命令行新建文件夹、新建文件,和一些常用命令
  18. Pycharm用Ctrl+鼠标滚轮控制字体大小
  19. HDU 1243 反恐训练营(最长公共序列)
  20. unity, 让主角头顶朝向等于地面法线(character align to surface normal)

热门文章

  1. yield学习
  2. Qt-QML-Popup,弹层界面编写
  3. PyMySQL连接MySQL数据库
  4. Java中二进制数与整型之间的转换
  5. 150命令之线上查询及帮助命令 man hellp
  6. 关于docker 基础使用记录
  7. 如何做好FAE工作及FAE职位发展
  8. Python中的list
  9. C语言 内存分配 地址 指针 数组 参数 实例解析
  10. Divide two integers without using multiplication, division and mod operator.