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=500000+10;
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<<2];
void push(int x)
{
    if(!ax) return;
    milsx+=ax;
    mirsx+=ax;
    alsx+=ax;
    arsx+=ax;
    ax=0;
}
void build(int l,int r,int x)
{
    if(l==r)
    {
        mix=l,lx=l,rx=r;ax=0;return;
    }
    int mid=(l+r)>>1;
    lx=l,rx=r,ax=0;
    build(l,mid,lsx);
    build(mid+1,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)>>1;
    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+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
     fa[i]=int(i/k),size[i]=1;
    for(int i=n-1;i;i--)
     if(a[i]==a[i+1]) nxt[i]=nxt[i+1]+1;
    for(int i=n;i;i--)
     size[fa[i]]+=size[i];

}
int main()
{
    scanf("%d%lf",&n,&k);
    for(int i=1;i<=n;i++)
     scanf("%d",&a[i]);
    prework();
    int root=1;
    build(1,n,root);
    for(int i=1;i<=n;i++)
    {
        if(fa[i]!=fa[i-1]) add(ans[fa[i]],n,root,size[fa[i]]-1);
        int p=find(root,size[i]);
        p+=nxt[p];nxt[p]++;p-=nxt[p]-1;ans[i]=p;
        add(p,n,root,-size[i]);
    }
    for(int i=1;i<=n;i++)
     printf("%d ",a[ans[i]]);
    return 0;
}

原文地址:https://www.cnblogs.com/Miracevin/p/9031549.html

时间: 2024-08-11 20:01:57

2018 省选 D1T2 IIIDX的相关文章

2018黑龙江省选总结

从我和LX,LCJ两位队友一起组队已经有一段时间了,毕竟刚进行组合,在训练的时候还需要很多磨合的地方,不如老队伍之间配合的默契,在训练的初期需要磨合,毕竟acm和OI不是很一样,对于思路的讨论不只是自己的思考,也需要让队友了解你的想法,即使想法是错的,但正解有可能就藏在其中,对于省选之前的训练,结束以后大家都会分一下补题,补题大体来说也还算顺利,毕竟训练的时候一般都会有一个想法,然后赛后询问其他人,基本也是同样的方法,总是会被卡在初始化写错或者题意理解的有偏差之类的,对于初始化总是写错这件事,基

如何将C/C++程序转译成Delphi(十四)

众所周知,数据科学是这几年才火起来的概念,而应运而生的数据科学家(data scientist)明显缺乏清晰的录取标准和工作内容.此次课程以<星际争霸II>回放文件分析为例,集中在IBM Cloud相关数据分析服务的应用.面对星际游戏爱好者希望提升技能的要求,我们使用IBM Data Science Experience中的jJupyter Notebooks来实现数据的可视化以及对数据进行深度分析,并最终存储到IBM Cloudant中.这是个介绍+动手实践的教程,参会者不仅将和讲师一起在线

世界著名设计小组nrg推荐的75个FLASH酷站

众所周知,数据科学是这几年才火起来的概念,而应运而生的数据科学家(data scientist)明显缺乏清晰的录取标准和工作内容.此次课程以<星际争霸II>回放文件分析为例,集中在IBM Cloud相关数据分析服务的应用.面对星际游戏爱好者希望提升技能的要求,我们使用IBM Data Science Experience中的jJupyter Notebooks来实现数据的可视化以及对数据进行深度分析,并最终存储到IBM Cloudant中.这是个介绍+动手实践的教程,参会者不仅将和讲师一起在线

铺揭竟冒剐惹蒲掷咕堑接veld

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

支酸权我据好张近拉其深就率sJFlzqgrA

社保划到税务征收,将大大提升社保费的征管效率.税务的征管能力是目前而言最强的,以后税务征收社保不是代收,属于本职了. 之前税局要把社保信息和交个税的工资比对起来有困难!现在好了,个税是自己的,社保也是自己的,比对困难?不存在的! 这一变革,会给那些不给员工上社保.不全额上社保的企业致命一击! 最新案例 前段时间的发改委关于限制特定严重失信人乘坐民航的一则意见--发改财金[2018]385号,其中还有税务总局的联合署名. http://weibo.com/20180408PP/2309279811

此每究具条如书中深花等业从次BaefoZ16

社保划到税务征收,将大大提升社保费的征管效率.税务的征管能力是目前而言最强的,以后税务征收社保不是代收,属于本职了. 之前税局要把社保信息和交个税的工资比对起来有困难!现在好了,个税是自己的,社保也是自己的,比对困难?不存在的! 这一变革,会给那些不给员工上社保.不全额上社保的企业致命一击! 最新案例 前段时间的发改委关于限制特定严重失信人乘坐民航的一则意见--发改财金[2018]385号,其中还有税务总局的联合署名. http://weibo.com/20180408PP/2309279811

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

bzoj 5249 [2018多省省队联测] IIIDX Link Solution 首先想到贪心,直接按照从大到小的顺序在后序遍历上一个个填 但是这样会有大问题,就是有相同的数的时候,会使答案不优 比如考虑 \((1, 2)(1, 3)(2, 4)\) 这样一棵树,并且点权是 \({1,1,1,2}\) 那么直接贪心会使得答案为 \(v_1=1,v_2=1,v_3=1,v_4=2\),但是实际上最优解为 \(v_1=1,v_2=1,v_3=2,v_4=1\) 问题出在我们先考虑 \(v_2\)

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

P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了. 这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻.同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高. 题目描述 这一天,Konano 接到了一个任务

2018适合编程入门的语言选什么好?Java语言好

互联网+时代,给我们呈现的完全是一个新景象,在新的景象当中,人们也会有新的追求,不少朋友的新追求就是进入互联网行业,怎么样入门互联网行业,他们的选择就是选择从一门编程语言开始,编程语言种类繁多,2018适合编程入门的语言选什么好?Java语言好.跟长沙尚学堂小编一起来看看具体原因. 很多朋友刚开始没有接触过编程语言,然后搜索了下编程语言,结果发现这是个庞大的家族,不可能所有的编程语言都学习一遍,同时开展好几门编程语言的学习,也不太靠谱,所以必须选择一门编程语言入门,很多朋友面临众多的编程语言不知