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 ...
随机推荐
- Mvc_ActionResult返回值
//ViewResult 表示HTML的页面内容 //EmptyResult 表示空白的页面内容 //RedirectResult 表示定位到另外一个URL //JsonResult 表示可以运用到A ...
- CentOS6.9下升级默认的OpenSSH操作记录(升级到OpenSSH_7.6p1)
近期对IDC机房服务器做了一次安全漏洞扫描,漏扫结果显示服务器的OpenSSH版本太低(CentOS6默认是OpenSSH_5.3p1),存在漏洞隐患,安全部门建议升级到OpenSSH_7.6p1.升 ...
- 分布式监控系统Zabbix-3.0.3-完整安装记录(1)
分布式监控系统Zabbix-3.0.3的安装记录 环境说明zabbix-server:192.168.1.30 #zabbix的服务端(若要监控本机,则需要配置本机的Zabbix agent, ...
- python-批量添加图片水印
前言: 最近总是被无良公众号和培训机构拷贝文章,他们根本不会给你备注原文出处,这种行为真的让人不高兴,所以计划以后的文章都添加上自己的水印. 话不多说,直接上代码. 一.单张图片添加文字水印 # -* ...
- 软件项目第一次sprint评论
软件项目第一次sprint评论 组名:天线宝宝四人组 姓名:高长志 1. 组名:9-652组 项目:炸弹人游戏 对于炸弹人游戏,首先 ...
- C++课程学习建议
从C到C++,学院都采用了机房授课模式,也在探索更为高效的实践与理论融合的教学方法,对于课程学习来说,仍有以下建议: 1.多看书.看书是理解基本概念的必备手段.也是学习的根本.应将课前预习.课后复习联 ...
- javac编译提示错误需要为 class、interface 或 enum
HelloWorld.java:1: 需要为 class.interface 或 enum锘缝ublic class HelloWorld{^1 错误 这个错误出现的原因主要是在中文操作系统中,使用一 ...
- Ajax进阶 FormData对象
Ajax基础:http://www.cnblogs.com/-beyond/p/7919369.html xhr 2.0及FormData介绍 FormData对象 其实和 XMLHttpReques ...
- MyBatis自动生成Java/C#的Bean(Entity)的等价MYSQL实现函数
这是单元测试代码:TESTTITLECASE.sql SELECT TITLECASE('ABC_DEF_hgk') as BEANNAME FROM DUAL; SELECT TITLECASE(' ...
- Enum service under CentOS7
service --status all systemctl list-unit-files