2018 省选 D1T2 IIIDX
题目大意:
给出k、n个数选择一种字典序最大的排列,使得对于任意的i,di>=d[i/k](下取整 下同)
分析:
很容易想到的是建树,将i的父亲设为[i/k],之后建有向边。
60分贪心:
将原先的a数组升序排列,直接根据子树大小分配排位。pai[i]=(同层级剩余的)-(子树大小)+1; 然而对于di有相同的情况时,也许可能会使得子树之间值发生交换,仍使得命题成立。
例如: [1,2,2,3] k=2;
正解:[1,2,3,2]
贪心: [1,2,2,3]
问题在于,因为题目中说了满足单调不降即可,而贪心则极力向后取数,可能会将大的数预留给自己较大编号的后代。如这个例子中,2号取到了3号排位,将4号排位、最大的3留给了4号。而3号就只剩下了2号排位。
我们想最大化较小的编号的值,就让它尽量往后取排位。 但是由于单调不降,可以让2号取2号位,4号取3号位,3号取4号位。使得答案更优。
正解:
线段树。
令原数组a降序排列。 令f[i]表示i号排位左边还有几个位置上的数是可以取到的。线段树维护这个区间内f的最小值。
显然这个f数组单调不降。对于从小到大的第i个编号,我们每次二分一个x,使得找到一个最靠左的位置,使得f[x]>=size[i],若有多个x,找到最靠右的一个x(这样使得在x取值最优时,尽可能将大的数留给后面的数。)让[x~n]区间上的值都减去size[i]
具体实现:
1.先判断到了i号点时,有没有进入下一个层级,如果有,将上一个层级预留的值都加回来(+size[fa]-1),才能二分、利用。
2.二分找到一个p;将p移动到同一个数值的、未用过的最右边。
3.将p赋值给ans[i],记录该p已经被用过(详见代码中nxt[p]++,这样保证下次减回来能多减一个位置)
4.给子树预留位置。
详见代码:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=+;
int nxt[N],a[N],ans[N],fa[N],size[N];
int n;
double k;
struct node{
int mi,l,r;
int add;
#define mix t[x].mi
#define lx t[x].l
#define rx t[x].r
#define lsx x<<1
#define rsx x<<1|1
#define ax t[x].add
#define milsx t[lsx].mi
#define mirsx t[rsx].mi
#define alsx t[x<<1].add
#define arsx t[x<<1|1].add
}t[N<<];
void push(int x)
{
if(!ax) return;
milsx+=ax;
mirsx+=ax;
alsx+=ax;
arsx+=ax;
ax=;
}
void build(int l,int r,int x)
{
if(l==r)
{
mix=l,lx=l,rx=r;ax=;return;
}
int mid=(l+r)>>;
lx=l,rx=r,ax=;
build(l,mid,lsx);
build(mid+,r,rsx);
mix=min(mirsx,milsx);
}
void add(int l,int r,int x,int c)
{
if(l<=lx&&rx<=r)
{
mix+=c;
ax+=c;return;
}
push(x);
int mid=(lx+rx)>>;
if(l<=mid) add(l,r,lsx,c);
if(mid<r) add(l,r,rsx,c);
mix=min(milsx,mirsx);
}
int find(int x,int d)
{
if(lx==rx) return lx+(mix<d);
push(x);
if(mirsx<d) return find(rsx,d);
return find(lsx,d);
}
bool cmp(int a,int b) {return a>b;}
void prework()
{
sort(a+,a+n+,cmp);
for(int i=;i<=n;i++)
fa[i]=int(i/k),size[i]=;
for(int i=n-;i;i--)
if(a[i]==a[i+]) nxt[i]=nxt[i+]+;
for(int i=n;i;i--)
size[fa[i]]+=size[i]; }
int main()
{
scanf("%d%lf",&n,&k);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
prework();
int root=;
build(,n,root);
for(int i=;i<=n;i++)
{
if(fa[i]!=fa[i-]) add(ans[fa[i]],n,root,size[fa[i]]-);
int p=find(root,size[i]);
p+=nxt[p];nxt[p]++;p-=nxt[p]-;ans[i]=p;
add(p,n,root,-size[i]);
}
for(int i=;i<=n;i++)
printf("%d ",a[ans[i]]);
return ;
}
2018 省选 D1T2 IIIDX的更多相关文章
- 2018 省选 T1 一双木棋
题目描述 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子当且仅当 ...
- [游记] Noip 2018
飞雪连天射白鹿, 笑书神侠倚碧鸳 $ 2018/12/14 $ 经历了 \(noip\) 玩完的心态爆炸之后,还是决定稍微写一下游记记录一下\(QAQ\),以免以后就忘了. 然后打算先写个框架之后再慢 ...
- 【科技】KD-tree随想
大概就是个复杂度对的暴力做法,在你不想写二维线段树等的时候优秀的替代品. 优点:思路简单,代码好写. 他大概有两种用法(虽然差不多). 在平面坐标系中干一些事情: 例如最常规的平面最近最远点,不管是欧 ...
- 一双木棋(chess)
一双木棋(chess) 题目描述 菲菲和牛牛在一块 nn 行 mm 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束.落子的规 ...
- 「九省联考 2018」IIIDX 解题报告
「九省联考 2018」IIIDX 这什么鬼题,送的55分要拿稳,实测有60? 考虑把数值从大到小摆好,每个位置\(i\)维护一个\(f_i\),表示\(i\)左边比它大的(包括自己)还有几个数可以选 ...
- 5249: [2018多省省队联测]IIIDX
5249: [2018多省省队联测]IIIDX 链接 分析: 贪心. 将给定的权值从大到小排序,从第一个往后挨个赋值,考虑第i个位置可以赋值那些树.首先满足前面必须至少有siz[i]个权值没选,如果存 ...
- bzoj 5249 [2018多省省队联测] IIIDX
bzoj 5249 [2018多省省队联测] IIIDX Link Solution 首先想到贪心,直接按照从大到小的顺序在后序遍历上一个个填 但是这样会有大问题,就是有相同的数的时候,会使答案不优 ...
- [luogu] P4364 [九省联考2018]IIIDX(贪心)
P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI ...
- [九省联考2018]IIIDX
题目描述 这一天,Konano接到了一个任务,他需要给正在制作中的游戏<IIIDX>安排曲目的解锁顺序.游戏内共有n首曲目 ,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第t ...
随机推荐
- JVM规范系列第3章:为Java虚拟机编译
Oracle 的 JDK 包括两部分内容:一部分是将 Java 源代码编译成 Java 虚拟机的指令集的编译器,另一部分是用于Java 虚拟机的运行时环境. 第一部分应该说的是 Javac 这个前置编 ...
- Quartz.net 定时任务之储存与持久化和集群(源码)
一.界面 1.这篇博客不上教程.直接看结果(包括把quartz任务转换成Windows服务) (1).主界面 (2).添加任务(默认执行) (3).编辑(默认开启) (4).关闭和开启 2.代码说明 ...
- Redis常用操作-------Key(键)
1.DEL key [key ...] 删除给定的一个或多个 key . 不存在的 key 会被忽略. 可用版本: >= 1.0.0 时间复杂度: O(N), N 为被删除的 key 的数量. ...
- alpa开发阶段团队贡献分
这是我们团队之前决定的分配方式: 1.凡是认真完成自己任务的队员,都将有基础分30分(态度分). 2. 将整个项目细化为不同的任务,列出一个任务清单,在综合.协调完每名成员的意愿后,我会分配清单中的任 ...
- StringBuffer的append方法比“+”高效
在字符串的连接过程中StringBuffer的效率要比String高: string操作代码: String str = new String("welcome to "); st ...
- Windows 7 64位安装cURL
安装cURL. 1, 下载64位的SSL版cURL,网址: http://curl.download.nextag.com/download/curl-7.21.7-win64-ssl-sspi.zi ...
- maven上传本地jar包到私服
场景 1. 本地jar包上传到私服 思路: 1. maven的settting.xml配置私服的帐号密码 2. pom.xml配置上传的地址 3. 执行 mvn deploy 部署jar包到私服 步骤 ...
- 编写一个shell脚本来编译并运行java代码
概述 编译和运行java分别要用到javac命令和java命令,虽然可以使用IDE(比如eclipse,InteliJ,NetBean...),按一下快捷键就可以实现编译并运行,但是,在之前还要配置一 ...
- PAT 1039 到底买不买
https://pintia.cn/problem-sets/994805260223102976/problems/994805283241443328 小红想买些珠子做一串自己喜欢的珠串.卖珠子的 ...
- windows 与linux 上面PG的简单验证
0.0 目的 验证一下 windows 上面 和linux上面的数据文件是否可以 冷备份 恢复. 1 方法关闭 windows机器上面postgresql 的服务 我这边是PG10.4 可以使用命令 ...