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


    Description

    【题目背景】
    Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏。现在
    ,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了。这款音乐游戏内一般都包含了许多歌曲,歌曲
    越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲
    目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。
    【题目描述】
    这一天,Konano接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目的解锁顺序。游戏内共有n首曲目
    ,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第trunc(i/k)首曲目后解锁(x为下取整符号)若tru
    nc(i/k)=0,则说明这首曲目无需解锁。举个例子:当k=2时,第1首曲目是无需解锁的(trunc(1/2)=0),第7首曲
    目需要玩家Pass第trunc(7/2)=3首曲目才会被解锁。Konano的工作,便是安排这些曲目的顺序,使得每次解锁出的
    曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i满足Di≥Dtrun
    c(i/k)。当然这难不倒曾经在信息学竞赛摸鱼许久的Konano。那假如是你,你会怎么解决这份任务呢
     

    Input

    第1行1个正整数n和1个小数k,n表示曲目数量,k其含义如题所示。
    第2行n个用空格隔开的正整数d,表示这n首曲目的难度。
    1 ≤ n ≤ 500000
    1 < k ≤ 10^9
    1 < d ≤ 10^9

    Output

    输出1行n个整数,按顺序输出安排完曲目顺序后第i首曲目的难度。
    若有多解,则输出d1最大的;若仍有多解,则输出d2最大的,以此类推。

    Sample Input

    4 2.0
    114 514 1919 810

    Sample Output

    114 810 514 1919
     
     
     
    贪心写挂了一分都没有
    正解好像还是挺好写的
    先sort一下
    用线段树维护比第i个点大的还没有被用到的数的个数f[i]
    每次选择最大的一个d[i]使得f[i]~f[n]都大于当前子树的大小
    然后f[i]~f[n]都减去这个子树的大小
    有点小细节
    每次枚举到一个点的时候需要把它对他父亲的限制的贡献减去
    有相同的a[i]要选最右边的那个
    想清楚了就很好码了
    //%std
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    using namespace std;
    #define lovelive long long
    #define lc son[x][0]
    #define rc son[x][1]
    #define lowbit(x) (x&(-x))
    #define pt vc
    const int N=5e5+100;
    void read(int &x)
    {
      int p=1;
      x=0;
      char c=getchar();
      while(c<'0'||c>'9')
      {
        if(c=='-')
          p=-1;
        c=getchar();
      }
      while(c>='0'&&c<='9')
      {
          x=x*10+c-48;
          c=getchar();
      }
      x*=p;
    }
    struct tree{
      int l,r;
      int sum,lazy;
    }t[N*4];
    void buildtree(int i,int l,int r)
    {
      t[i].l=l;
      t[i].r=r;
      if(l==r)
      {
        t[i].sum=l;
        return;
      }
      int mid=(l+r)>>1;
      buildtree(i<<1,l,mid);
      buildtree(i<<1|1,mid+1,r);
      t[i].sum=min(t[i<<1].sum,t[i<<1|1].sum);
    }
    void pushdown(int i)
    {
      if(!t[i].lazy)
        return;
      t[i<<1].sum+=t[i].lazy;
      t[i<<1|1].sum+=t[i].lazy;
      t[i<<1].lazy+=t[i].lazy;
      t[i<<1|1].lazy+=t[i].lazy;
      t[i].lazy=0;
    }
    void change(int i,int l,int r,int x)
    {
      if(l>t[i].r||r<t[i].l)
        return;
      if(l<=t[i].l&&t[i].r<=r)
      {
          t[i].sum+=x;;
          t[i].lazy+=x;
          return;
      }
      pushdown(i);
      change(i<<1,l,r,x);
      change(i<<1|1,l,r,x);
      t[i].sum=min(t[i<<1].sum,t[i<<1|1].sum);
    }
    int find(int x)
    {
      int i=1,r;
      if(t[i].sum>=x)
        return 1;
      while(1)
      {
          if(t[i].l==t[i].r)
            break;
        pushdown(i);
          if(t[i<<1|1].sum>=x)
            r=t[i<<1|1].l,i=i<<1;
          else
            i=i<<1|1;
      }
      return r;
    }
    int d[N],ans[N],fa[N],siz[N];
    int nxt[N];
    int main()
    {
      int n,x;
      double k;
    //  freopen("iiidx.in","r",stdin);
    //  freopen("iiidx.out","w",stdout);
      read(n);scanf("%lf",&k);
      for(int i=1;i<=n;i++)
        fa[i]=floor(i/k+1e-10);
      for(int i=n;i>=1;i--)
          siz[fa[i]]+=++siz[i];
      for(int i=1;i<=n;i++)
        read(d[i]);
      sort(d+1,d+n+1);
      for(int i=1;i<=n;i++)
        if(i<n-i+1)
          swap(d[i],d[n-i+1]);
      nxt[n]=n;
      for(int i=n-1;i>=1;i--)
        if(d[i+1]==d[i])
          nxt[i]=nxt[i+1];
        else
          nxt[i]=i;
      buildtree(1,1,n);
      for(int i=1;i<=n;i++)
      {
          if(fa[i])
            change(1,ans[fa[i]],n,siz[i]);
          x=find(siz[i]);
          x=nxt[x];
          ans[i]=x;
          change(1,x,n,-siz[i]);
      }
      for(int i=1;i<=n;i++)
        cout<<d[ans[i]]<<" ";
      return 0;
    }
    View Code
  • 相关阅读:
    团队代码
    团队代码
    团队代码
    团队代码
    innerHTML与innerText与outHTML与outText 的区别。
    【C++】 C++知识点总结
    【海思】Hi3516A 运行sample_venc的demo内核奔溃(DDR问题)
    【C/C++】 C++寄存器优化
    【工具】 memtester内存压力测试工具
    【知识点】 gcc和g++的联系和区别
  • 原文地址:https://www.cnblogs.com/NicoDafaGood/p/8868249.html
Copyright © 2020-2023  润新知