转化一下问题变成给定一棵树,一个序列,求父亲的权值小于子树的最大方案。

直接贪心会在有重复权值时出现错误,我们考虑用线段树优化贪心。

将序列从小到大排序,线段树上每个点记录他和他右边当前还可用的权值,注意这里我们并不一定维护的都是正确的,但是我们要保证我们需要用到的限制一定都体现了出来,比如 1 2 5 5 5 5 5 6 7 8 9 K=2,我们放第二个点时,会放到3这个位置,于是我们将1~3区间减7,这时候4~11的权值我们并没有修改,但是需要用到的限制只有前三个点,所以是正确的,之后我们每次在线段树上找到最大的可用位置,然后放到和他权值相同的最左边就可以了。

还要注意我们放一个点时需要先将其父亲的限制去掉。

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#define N 500500
using namespace std;
int n,a[N],fa[N],size[N],pp[N];
double K;
int lazy[N<<],minn[N<<];
void pushdown(int rt){
if(lazy[rt]){
lazy[rt<<]+=lazy[rt];minn[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];minn[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void build(int rt,int l,int r){
if(l==r){minn[rt]=n-l+;return;}
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
minn[rt]=min(minn[rt<<],minn[rt<<|]);
}
void update(int rt,int l,int r,int x,int y,int z){
if(x<=l&&r<=y){
lazy[rt]+=z;minn[rt]+=z;
return ;
}
pushdown(rt);
int mid=(l+r)>>;
if(x<=mid)update(rt<<,l,mid,x,y,z);
if(y>mid)update(rt<<|,mid+,r,x,y,z);
minn[rt]=min(minn[rt<<],minn[rt<<|]);
}
int query(int rt,int l,int r,int x){
if(l==r){
if(minn[rt]>=x)return l;
return l-;
}
pushdown(rt);
int mid=(l+r)>>;
if(minn[rt<<]>=x)return query(rt<<|,mid+,r,x);
else return query(rt<<,l,mid,x);
}
map<int,int> L;
int main(){
scanf("%d%lf",&n,&K);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
sort(a+,a+n+);
for(int i=;i<=n;i++)
if(a[i]!=a[i-])L[a[i]]=i;
for(int i=;i<=n;i++)fa[i]=floor(i/K);
for(int i=n;i;i--){
size[i]++;
size[fa[i]]+=size[i];
}
build(,,n);
for(int i=;i<=n;){
if(fa[i])update(,,n,,pp[fa[i]],size[fa[i]]-);
do{
int x=query(,,n,size[i]);
pp[i]=L[a[x]]++;
update(,,n,,pp[i],-size[i]);
i++;
}while(i<=n&&fa[i]==fa[i-]);
}
for(int i=;i<=n;i++)printf("%d%c",a[pp[i]],((i==n)?'\n':' '));
return ;
}

bzoj5249 [2018多省省队联测]IIIDX的更多相关文章

  1. bzoj千题计划324:bzoj5249: [2018多省省队联测]IIIDX(线段树)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5249 把树建出来 如果所有的d互不相同,后续遍历即可 现在有的d相同 将d从小到大排序,考虑如何将 ...

  2. BZOJ5249: [2018多省省队联测]IIIDX(线段树 贪心)

    题意 题目链接 Sol 不难发现题目给出的是一个树,其中\(\frac{i}{K}\)是\(i\)的父亲节点 首先,当\(d_i\)互不相同时,一个显然的贪心策略就是优先给编号小的分配较大的权值.可以 ...

  3. 5249: [2018多省省队联测]IIIDX

    5249: [2018多省省队联测]IIIDX 链接 分析: 贪心. 将给定的权值从大到小排序,从第一个往后挨个赋值,考虑第i个位置可以赋值那些树.首先满足前面必须至少有siz[i]个权值没选,如果存 ...

  4. bzoj 5249 [2018多省省队联测] IIIDX

    bzoj 5249 [2018多省省队联测] IIIDX Link Solution 首先想到贪心,直接按照从大到小的顺序在后序遍历上一个个填 但是这样会有大问题,就是有相同的数的时候,会使答案不优 ...

  5. BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)

    题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...

  6. 【刷题】BZOJ 5249 [2018多省省队联测]IIIDX

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

  7. BZOJ_5249_Luogu_P4364_[2018多省省队联测]_IIIDX_九省联考2018_JLOI2018_线段树

    BZOJ_5249_[2018多省省队联测]IIIDX_线段树 Description [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐 ...

  8. bzoj 5248: [2018多省省队联测]一双木棋

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

  9. bzoj 5251: [2018多省省队联测]劈配

    Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 题目描述 轻车熟路的Zayi ...

随机推荐

  1. Demo2

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  2. java 多线程例子

    java 多线程例子   编写具有多线程能力的程序经常会用到的方法有: run(), start(), wait(), notify(), notifyAll(), sleep(), yield(), ...

  3. Getting Real内容浓缩

    今天看完,想整理一下,可能会更好,也给别人提供一个快速学习的途径第一章 什么是 Getting Real?表达形式省略.精炼.精益.敏捷.用户体验.迭代改进.产品简化.第二章 建构从简做得比竟争对手少 ...

  4. 竞品调研时发现的Android新设计特性

    先share两篇技术层面的文章: Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用:http://blog ...

  5. android开发过程中遇到的坑

    在android的学习过程中,会有很多坑,我会把我遇到的,一一列下来,方便后来者查阅! 1:android-support-v4.jar and android-support-v7-appcompa ...

  6. C++ 延时等待(sleep/timer/wait)

    原文链接:http://blog.csdn.net/tangweide/article/details/7063747 (-)使用_sleep()函数 #include <iostream> ...

  7. 如何优雅的关闭Java线程池

    面试中经常会问到,创建一个线程池需要哪些参数啊,线程池的工作原理啊,却很少会问到线程池如何安全关闭的. 也正是因为大家不是很关注这块,即便是工作三四年的人,也会有因为线程池关闭不合理,导致应用无法正常 ...

  8. JavaScript中push ,pop ,concat ,join方法

    push 方法 将新元素添加到一个数组中,并返回数组的新长度值. arrayObj.push([item1 [item2[. . . [itemN ]]]]) 说明 push 方法将以新元素出现的顺序 ...

  9. golang自定义路由控制实现(一)

        由于本人之前一直是Java Coder,在Java web开发中其实大家都很依赖框架,所以当在学习Golang的时候,自己便想着在Go开发中脱离框架,自己动手造框架来练习.通过学习借鉴Java ...

  10. Fibonacci数列使用迭代器实现

    Fibonacci数列,数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... class FibItera ...