「九省联考 2018」IIIDX 贪心 线段树

【题目背景】

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

这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。

【题目描述】

这一天,Konano 接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目的解锁顺序。游戏内共有 n n 首曲目,每首曲目都会有一个难度 d,游戏内第 i i 首曲目会在玩家 Pass 第 ik 首曲目后解锁( x ⌊ x ⌋ 为下取整符号)若 ik=0 ⌊ i k ⌋ = 0 ,则说明这首曲目无需解锁

举个例子:当 k=2 k = 2 时,第 1 1 首曲目是无需解锁的(12=0),第 7 7 首曲目需要玩家 Pass 第 72=3 首曲目才会被解锁。

Konano 的工作,便是安排这些曲目的顺序,使得每次解锁出的曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个 i i 满足 didik

当然这难不倒曾经在信息学竞赛摸鱼许久的 Konano。那假如是你,你会怎么解决这份任务呢?

【数据范围】
测试点编号 n n k d d 特殊限制
1 1n10 1 ≤ n ≤ 10 k=2 k = 2 1d100 1 ≤ d ≤ 100 保证 di d i 互不相同
2 2 k=3
3 3 k=1.1
4 4 k=n
5 5 1<k100
6 6
7 1n2000 1 ≤ n ≤ 2000 k=2 k = 2 1d109 1 ≤ d ≤ 10 9 保证 di d i 互不相同
8 8
9 k=3 k = 3 保证 di d i 互不相同
10 10
11 11 1<k109 1 < k ≤ 10 9 保证 di d i 互不相同
12 12
13 13 1n500000 1 ≤ n ≤ 500000 k=2 k = 2
14 14 k=3 k = 3
15 15 1<k109 1 < k ≤ 10 9 保证 di d i 互不相同
16 16
17 17
18 18
19 19
20 20

题解

首先考虑部分分的做法。
很显然可以发现,本题对于歌曲解锁的顺序限制是一个树形的结构,这样一来,题目的要求就可以变成把一堆数放到一颗树上,使得儿子均比父亲来得大,并且要求解最大。
贪心地来想,好像按树的后序遍历从大到小放数字就是最优解了。
然而   ⋯   ,如果数有相同,那么就会出现一些不对的情况。
假设我们的序列是这样

k=2 , d={6,6,6,9} k = 2   ,   d = { 6 , 6 , 6 , 9 }

那么贪心: {6,6,6,9} { 6 , 6 , 6 , 9 }
然而正解: {6,6,9,6} { 6 , 6 , 9 , 6 }
于是我们的贪心就不对了,这个时候该怎么办呢?
我们仍然是贪心,只不过这一次,我们保证每一个节点都确定了尽量大的数,再依次往后确定。
举个例子,假如 d={9,9,8,2,4,4,3,5,3} d = { 9 , 9 , 8 , 2 , 4 , 4 , 3 , 5 , 3 } ,排序后 {2,3,3,4,4,5,8,9,9} { 2 , 3 , 3 , 4 , 4 , 5 , 8 , 9 , 9 }
若第一个点的子树大小为 5 5 那么这个点的值就是第 5 大的数字, 4 4
不过 4 有很多个啊,我们就钦定取最左的 4 4 ,也就是第 6 个数。那么这样一来,我们就要在区间 [6,9] [ 6 , 9 ] 里面预留 4 4 个节点放在这个点的子树中。
怎么解决这样的预留的问题呢?
我们记 fi 表示第 i i 个点右边已经被预留了 fi 个数了,这样我们就能知道 i i 右边可用的数有 ifi 个。
对于上面这种情况,我们就将 f1 f 1 f3 f 3 都加上 4 4
一般地,当我们处理到第 i 个节点时,设其子树大小为 sizei s i z e i
那么找一个最小的位置 p p ,使得 jfj (jp)sizei,并将 p p 上的数给 i 这个点就行了。若是 i i 有父亲,那么就要把 i 父亲节点的预留给去掉。

也可以换一种理解方式,就是我们每次贪心地选一个数以后,都要保证预留一些树来放在这个点的子树中,于是我们就一步步做然后保证不矛盾就行了。接着在这个基础上使得解最大。

于是我们开一颗线段树,就能维护上面那些区间修改和查询了。
其实线段树只需要直接维护 ifi i − f i 就行了。
(我才不会说我从小到大排序是因为不想用 greater greater 的)

代码

60分贪心:
#include<bits/stdc++.h>
using namespace std;
#define R register
const int maxn = 5e5+10;
struct Edge{
    int To;
    Edge *Next;
}*Head[maxn];
inline void Add(R int u,R int v){
    static Edge E[maxn],*e=E;
    *e=(Edge){v,Head[u]};Head[u]=e++;
}
int n,d[maxn],*c=d;
double k;
int fa[maxn];
int Ans[maxn];
void dfs(R int u){
    for(R Edge *i=Head[u];i;i=i->Next){
        dfs(i->To);
    }
    if(u)Ans[u]=*++c;
}
int main(){
    scanf("%d %lf",&n,&k);
    for(R int i=1;i<=n;++i)scanf("%d",d+i);
    sort(d+1,d+1+n,greater<int>());
    for(R int i=n;i;i--){
        fa[i]=(int)(1.0*i/k);
        Add(fa[i],i);
    }
    dfs(0);
    for(R int i=1;i<=n;++i)printf("%d ",Ans[i]);
    return 0;
}
Accept
#include <bits/stdc++.h>
#define R register
#define LL long long
template<class TT>inline TT Max(R TT a,R TT b){return a<b?b:a;}
template<class TT>inline TT Min(R TT a,R TT b){return a<b?a:b;}
using namespace std;
template<class TT>inline void read(R TT &x){
    x=0;R bool f=false;R char c=getchar();
    for(;c<48||c>57;c=getchar())f|=(c=='-');
    for(;c>47&&c<58;c=getchar())x=(x<<1)+(x<<3)+(c^48);
    (f)&&(x=-x);
}
int happy;
const int maxn = 1000010;

int n,d[maxn];
double k;

//Graph
int tp;
struct Edge{
    int to;
    Edge *next;
}*head[maxn];
inline void Add(R int u,R int v){
    static Edge E[maxn],*e=E;
    *e=(Edge){v,head[u]};head[u]=e++;
}
//end

//segment_tree
#define Ls (i<<1)
#define Rs (i<<1|1)
int s[1<<20],t[1<<20];
inline void push_down(R int i){
    if(t[i]){
        R int x=t[i];
        t[Ls]+=x;
        t[Rs]+=x;
        s[Ls]+=x;
        s[Rs]+=x;
        t[i]=0;
    }
}
#define defvar R int l,R int r,R int i
void build(defvar){
    if(l==r){s[i]=n-l+1;return;}
    R int mid=l+r>>1;
    build(l,mid,Ls);
    build(mid+1,r,Rs);
    s[i]=Min(s[Ls],s[Rs]);
}
void add(defvar,R int ql,R int qr,R int qx){
    if(ql<=l&&r<=qr){
        s[i]+=qx;
        t[i]+=qx;
        return;
    }
    push_down(i);
    R int mid=l+r>>1;
    if(ql<=mid)add(l,mid,Ls,ql,qr,qx);
    if(qr>mid)add(mid+1,r,Rs,ql,qr,qx);
    s[i]=Min(s[Ls],s[Rs]);
}
int query(defvar,R int qp,R int qx){
    R int mid=l+r>>1,x=0;
    if(qp<=l){
        if(s[i]>=qx)return 0;
        if(l==r)return l-1;
        push_down(i);
        if(s[Ls]>=qx){
            x=query(mid+1,r,Rs,qp,qx);
            s[i]=Min(s[Ls],s[Rs]);
            return x;
        }
        if(s[Ls]<qx){
            x=query(l,mid,Ls,qp,qx);
            if(x)return x;
        }
        return l-1;
    }
    push_down(i);
    if(qp<=mid)x=query(l,mid,Ls,qp,qx);
    if(!x)x=query(mid+1,r,Rs,qp,qx);
    s[i]=Min(s[Ls],s[Rs]);
    return x;
}
//end

//get size
int siz[maxn];
void dfs(R int u){
    siz[u]=1;
    for(R Edge *i=head[u];i;i=i->next){
        dfs(i->to);
        siz[u]+=siz[i->to];
    }
}
//end
int fa[maxn];
int st[maxn],pos[maxn],lth[maxn];
int main(){
    read(n);
    happy=scanf("%lf",&k);
    for(R int i=1;i<=n;++i)read(d[i]);
    for(R int i=1;i<=n;++i){
        fa[i]=1.0*i/k;
        Add(fa[i],i);
    }
    dfs(0);
    sort(d+1,d+1+n);
    build(1,n,1);
    for(R int i=1;i<=n;++i){
        if(d[i]!=d[i-1])st[i]=i;
        else st[i]=st[i-1];
    }
    for(R int i=1,p;i<=n;++i){
        p=query(1,n,1,pos[fa[i]]+1,siz[i]);
        if(!p)p=n-siz[i]+1;
        p=st[p]+lth[st[p]];
        printf("%d ",d[p]);
        lth[st[p]]++;
        pos[i]=p;
        add(1,n,1,pos[fa[i]]+1,p,-siz[i]);
    }
    return 0;
}
### 回答1: 黄河九省地图数据Shp是一种包含九个省份的地理信息系统文件格式,可以在各种GIS软件中使用。这些九个省份包括青海、甘肃、宁夏、内蒙古、陕西、山西、河南、山东和河北。该地图数据Shp覆盖了全部黄河流域,以黄河为中心,包括了黄河流域内的山脉、河流、湖泊、城市、道路等地理要素。使用这个地图数据Shp可以提供各种黄河流域的地理信息分析与处理,如水文、水资源、水环境、地质灾害、城市规划、交通等领域。 该地图数据Shp由多个文件组成,其中包括.shp、.shx、.dbf等几个文件。其中.shp文件存储了地图数据几何图形信息,.shx文件存储了几何图形的索引信息,.dbf文件存储了属性数据信息。可以使用各种GIS软件打开这些文件,可以查看和编辑地图数据,进行地理信息分析和处理。 使用黄河九省地图数据Shp 可以进行各种有关黄河流域的地理信息分析和处理。例如,分析黄河流域内不同地区的地形、气候、土壤、地质等因素对河流水质、水量、水文周期以及水文气候等方面的影响。此外,还可以计算不同区域内的水资源量, 分析地区可能面临的水资源风险, 同时可以对水资源进行合理规划与管理。 总之,黄河九省地图数据Shp为黄河流域日常采集和分析水文资料提供了有力支持, 同时也可以支持城市建设和工程规划等方面的分析。因此,黄河九省地图数据Shp在黄河流域及周边地区的管理和规划等领域中具有广泛的应用前景。 ### 回答2: 黄河九省地图数据shp是一种包含有关中国黄河流域九个省份地理信息的数字地图文件。这些省份包括:青海、甘肃、宁夏、内蒙古、陕西、山西、河南、山东和河北。该地图文件将这些省份的边界和地理要素转换为几何图形,并将其存储在shp文件中,可实现对其进行空间分析和地图制作。 这个地图数据shp文件实用性很高,可以广泛应用于黄河流域相关的地理信息领域。例如,在自然资源管理方面,可以使用它来进行土地资源、水资源、气候资源和矿产资源的分析,以便有效管理和利用这些资源。而在交通运输、城市规划和环境保护方面,该文件可以用于路线规划、区域规划和环境监测,提高规划决策的准确性和精度。 此外,该地图数据shp文件可以应用在教育和科研领域,如地理信息系统、地理编码和遥感分析等方面,为学术研究和教学活动提供相关的数据支持和参考。总之,黄河九省地图数据shp文件是非常有价值的地理信息资源,对于研究和应用黄河流域相关的地理信息问题非常有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值