zoukankan      html  css  js  c++  java
  • [线段树] Luogu P4346 IIIDX

    题目背景

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

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

    题解

    • 先从大到小排序,每次找一个最靠左的位置,使得这个位置左边足够放下当前节点的子树

    • 若有多个值相同,应该放到最右边那个值那里

    • 显然满足单调性,毕竟如果某个位置可以满足,那么该位置右边的位置也一定能够满足

    • nxt 数组用来求同一个值的最右边在哪个位置。更新的时候向左移一个,防止取到相同的位置

    • 线段树修改的时候,最小值直接加上修改的值就行了,不用乘上区间长度,更新儿子节点的时候,要把他的父亲给他预留的位置先去掉

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <algorithm> 
     5 #define N 500010
     6 using namespace std;
     7 double k;
     8 int n,a[N],f[N],ans[N],size[N],fa[N],nxt[N],mn[N<<2],tag[N<<2];
     9 void build(int d,int l,int r)
    10 {
    11     if (l==r) { mn[d]=l; return;}
    12     int mid=l+r>>1; 
    13     build(d*2,l,mid),build(d*2+1,mid+1,r);
    14     mn[d]=min(mn[d*2],mn[d*2+1]);
    15 }
    16 void push(int d)
    17 {
    18     if (!tag[d]) return;
    19     mn[d*2]+=tag[d],mn[d*2+1]+=tag[d],tag[d*2]+=tag[d],tag[d*2+1]+=tag[d],tag[d]=0;
    20 }
    21 void change(int d,int L,int R,int x,int l=1,int r=n)
    22 {
    23     if (L<=l&&r<=R) { tag[d]+=x,mn[d]+=x; return; }
    24     int mid=l+r>>1; push(d);
    25     if (L<=mid) change(d*2,L,R,x,l,mid);
    26     if (R>mid) change(d*2+1,L,R,x,mid+1,r);
    27     mn[d]=min(mn[d*2],mn[d*2+1]);
    28 }
    29 int find(int d,int x,int l=1,int r=n)
    30 {
    31     if (l==r) return l+(mn[d]<x);
    32     int mid=l+r>>1; push(d);
    33     return x<=mn[d*2+1]?find(d*2,x,l,mid):find(d*2+1,x,mid+1,r);
    34 }
    35 int main()
    36 {
    37     scanf("%d%lf",&n,&k);
    38     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    39     sort(a+1,a+n+1),reverse(a+1,a+n+1);
    40     for (int i=n-1;i;i--) if (a[i]==a[i+1]) nxt[i]=nxt[i+1]+1;
    41     for (int i=1;i<=n;i++) fa[i]=i/k,size[i]=1;
    42     for (int i=n;i;i--) size[fa[i]]+=size[i];
    43     build(1,1,n);
    44     for (int i=1;i<=n;i++) 
    45     {
    46         if (fa[i]!=fa[i-1]) change(1,ans[fa[i]],n,size[fa[i]]-1);
    47         int p=find(1,size[i]);
    48         p+=nxt[p];nxt[p]++;p-=nxt[p]-1;ans[i]=p,change(1,p,n,-size[i]);
    49     }
    50     for (int i=1;i<=n;i++) printf("%d ",a[ans[i]]);
    51 }
  • 相关阅读:
    iOS总结_UI层自我复习总结
    runtime梳理。
    页面传值。顺传,逆传。
    用1 + 2 = 3诠释面向对象思想
    循环逻辑。让我逻辑滞空的小题目
    const,static,extern 简介
    swift webView的高度自适应内容
    Swift之UITabBarController 导航控制器颜色的改变
    swift 启动图片的设置
    swift 中使用OC第三方库(以AFNetworking为例)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11235694.html
Copyright © 2011-2022 走看看