Description

题库链接

给你 \(n+1\) 个节点的一棵树,节点编号为 \(0\sim n\) , \(0\) 为根。边集为 \(\mathbb{E}=\left\{(u,v)\big|\forall i\in[1,n],\left(\left\lfloor\frac{i}{k}\right\rfloor,i\right)\right\}\) 。给出 \(n\) 个待选序号,让你为 \(1\sim n\) 这 \(n\) 个节点编号,第 \(i\) 号节点编为 \(a_i\),要求父亲编号小于等于儿子的编号。求满足要求的序列 \(a_1,a_2,\cdots,a_n\) 中字典序最大的一个。

\(1\leq n\leq 500000\)

Solution

直接递归贪心回溯时选一个未选的最大值是错的。

考虑为什么会出错,依旧举一个例子:

4 2
1 1 1 2

画成图就是:

如果按照刚才的贪心方式,我们会先将 \(2\) 赋给 \(4\) 号节点,再将 \(1\) 赋给 \(2\) 号节点。这样就错了,考虑为什么?

因为容易发现,不论怎么分配, \(2\) 号节点一定只能赋为 \(1\) ,这时被选的数中有两个 \(1\) ,等于说我们可以让 \(4\) 号点取 \(1\) ,这样是更优的。

那么之前的贪心就错了,但不过它提供了一个思路,就是对于一个节点的儿子们,一定是先尽可能将标号小的儿子的子树用大的标号标。唯一需要处理的就是子树的根节点的标号可能有多个相同的备选。

我们将被选数从大到小排序。一个节点按之前的方式编号,我们就要选与这个编号相同的最靠右的一个。这样能保证最优。

我们不用递归,我们只需要枚举节点时为其子树预留节点即可。

考虑线段树维护这样的一个数组 \(f\) ,\(f_i\) 表示 \(i\) 位置前有多少个数可选。

每次查询的时候只要找到这样的一个最靠左的位置 \(x\) ,使得 \(\forall i,f_i\geq size_i\) ,其中 \(size_i\) 为当前节点子树的大小。

然后将 \(x\) 赋为与这个编号相同的最靠右的一个的位置。那么这个位置的值就是被选值。

处理完之后,我们还要对 \(x\) 之后的 \(f\) 数组进行修改。

以上操作都可以用线段树维护。

值得注意的是由于处理到一个节点的时候,如果它有父亲,那么要将其父亲的预留的额度删去。

如果仍有不理解,可参见ppt

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 500000+5; int n, a[N], fa[N], nxt[N], size[N], ans[N]; double k;
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)
int minn[N<<2], tag[N<<2];
void pushdown(int o) {
minn[lr(o)] += tag[o], tag[lr(o)] += tag[o];
minn[rr(o)] += tag[o], tag[rr(o)] += tag[o];
tag[o] = 0;
}
void build(int o, int l, int r) {
if (l == r) {minn[o] = l; return; } int mid = (l+r)>>1;
build(lr(o), l, mid), build(rr(o), mid+1, r);
minn[o] = min(minn[lr(o)], minn[rr(o)]);
}
void update(int o, int l, int r, int a, int b, int k) {
if (a <= l && r <= b) {minn[o] += k, tag[o] += k; return; }
pushdown(o); int mid = (l+r)>>1;
if (a <= mid) update(lr(o), l, mid, a, b, k);
if (b > mid) update(rr(o), mid+1, r, a, b, k);
minn[o] = min(minn[lr(o)], minn[rr(o)]);
}
int query(int o, int l, int r, int k) {
if (l == r) return minn[o] >= k ? l : l+1;
pushdown(o); int mid = (l+r)>>1;
if (k <= minn[rr(o)]) return query(lr(o), l, mid, k);
else return query(rr(o), mid+1, r, k);
}
}T;
bool comp(const int &a, const int &b) {return a > b; } void work() {
scanf("%d%lf", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]); sort(a+1, a+n+1, comp);
for (int i = n; i >= 1; i--) {
nxt[i] = i, fa[i] = floor(1.*i/k);
++size[i]; size[fa[i]] += size[i];
if (a[i] == a[i+1]) nxt[i] = nxt[i+1];
}
T.build(1, 1, n);
for (int i = 1; i <= n; i++) {
if (fa[i] && fa[i] != fa[i-1]) T.update(1, 1, n, ans[fa[i]], n, size[fa[i]]-1);
int loc = nxt[T.query(1, 1, n, size[i])]; ans[i] = loc;
T.update(1, 1, n, loc, n, -size[i]);
}
for (int i = 1; i <= n; i++) printf("%d ", a[ans[i]]);
}
int main() {work(); return 0; }

[九省联考 2018]IIIDX的更多相关文章

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

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

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

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

  3. [九省联考2018]IIIDX

    题目描述 这一天,Konano接到了一个任务,他需要给正在制作中的游戏<IIIDX>安排曲目的解锁顺序.游戏内共有n首曲目 ,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第t ...

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

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

  5. BZOJ5249:[九省联考2018]IIIDX——题解

    https://www.luogu.org/problemnew/show/P4364#sub https://www.lydsy.com/JudgeOnline/problem.php?id=524 ...

  6. 洛谷P4364 [九省联考2018]IIIDX 【线段树】

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

  7. [luogu]P4364 [九省联考2018]IIIDX

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

  8. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  9. 解题:九省联考2018 IIIDX

    题面 我当时在考场上划水的时候好像乱搞搞了20pts,然后发现一堆同届的都写了55pts的贪心=.=??? 那就先说那55pts的贪心吧,这个现在看起来还是非常显然的,就是按题意来每一块是分属一个点的 ...

随机推荐

  1. [翻译]NUnit---TearDown and SetUpFixture and Test Attributes(二十)

    TearDownAttribute (NUnit 2.0 / 2.5) 本特性在TestFixture内部使用,每个测试方法执行后调用的方法集.也可以在SetUpFixture中使用,在同一命名空间或 ...

  2. 截图-----Selenium快速入门(十二)

    在自动化测试过程中,截图是常见的操作,因为有时候单靠程序无法判断是否已得到期望的结果,所以需要截图判断.又或者截图是作为判断的存证.Selenium的截图操作也是非常简单,而且自带了一个文件操作类Fi ...

  3. 如何连接MSSQLSERVER2014(其他版本数据库大体相同)

    购买了服务器后我在上面安装了SqlServer2014,但是程序中总是远程连接不上,特此记录一下: 一.一些基本设置如下链接: 转载自:https://blog.sun0816.com/20381.h ...

  4. 解决:百度编辑器UEditor,怎么将图片保存到图片服务器,或者上传到ftp服务器的问题(如果你正在用UE,这篇文章值得你看下)

    在使用百度编辑器ueditor的时候,怎么将图片保存到另一个服务器,或者上传到ftp服务器?这个问题,估计很多使用UE的人会遇到.而且我百度过,没有找到这个问题的解决方案.那么:本篇文章就很适合你了. ...

  5. C#一些代码小结--文件对话框

    C# 一些代码小结--文件对话框 查看文件完整路径 try { Config cfg = new Config(); var file = ""; if (saveFileDial ...

  6. C# 泛型实现Table与实体的相互转换

    public class ModelHandler<T> where T : new() { /// <summary> /// Table转换成实体 /// </sum ...

  7. 移植Max中的控制器到Unity - 前言

    一切源自于一个ppt http://pan.baidu.com/s/1kT8x2V9 看到这个ppt之前,其实自己也想过将Max当中的一些约束移植到游戏中,一方面是那时候能力不足,另一方面还是自己不那 ...

  8. S11 day 96 RestFramework 之认证权限

    一.设计一个简易的登录 1. 建立一个模型 class UserInfo(models.Model): username =models.CharField(max_length=) password ...

  9. Android逆向系列文章— Android基础逆向(6)

    本文作者:HAI_ 0×00 前言 不知所以然,请看 Android逆向-Android基础逆向(1) Android逆向-Android基础逆向(2) Android逆向-Android基础逆向(2 ...

  10. Elasticsearch Java API简介

    加入依赖 我本地的Elasticsearch的版本是2.1.0,因此加入相应的maven依赖 <dependency> <groupId>org.elasticsearch&l ...