• [九省联考2018]IIIDX


    题目大意:
      一个游戏有$n(nle5 imes10^5)$个关卡,每个关卡有一个难度系数$d_i(d_ile10^9)$。给定一个实数$k(kle10^9)$,表示关卡$i$依赖于关卡$lfloorfrac ik floor$,即只有当关卡通过$lfloorfrac ik floor$后,关卡$i$才会被解锁。问如何排列这些难度系数,使得$d_ige d_{lfloorfrac ik floor}$?求字典序最大的方案。

    思路:
      不难发现关卡间的依赖关系构成了一个树状结构。
      对于$d_i$各不相同的情况,只存在唯一的一种方案,直接贪心即可,期望得分60分。
      对于$d_i$相同的情况,用权值线段树维护大于当前难度值有多少未分配的难度值,从小到大枚举$1sim n$号点,对于第$i$号结点,将当前未分配的第$size[i]$大的难度值分配给该结点即可。考虑如何操作才能使得$d_i$之后的难度值一定分配给$i$的子树。在操作完$i$结点后,可以将前$size[i]$大的难度值在线段树上标记为已分配,当访问到$i$的第一个子结点时,再恢复这些难度值并进行分配。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int N=5e5+1;
    12 const double eps=1e-8;
    13 double k;
    14 int n,d[N],size[N],ans[N],par[N],pos[N];
    15 class SegmentTree {
    16     #define _left <<1
    17     #define _right <<1|1
    18     private:
    19         int cnt[N<<2],tag[N<<2];
    20         void push_up(const int &p) {
    21             cnt[p]=std::min(cnt[p _left],cnt[p _right]);
    22         }
    23         void push_down(const int &p) {
    24             tag[p _left]+=tag[p];
    25             tag[p _right]+=tag[p];
    26             cnt[p _left]+=tag[p];
    27             cnt[p _right]+=tag[p];
    28             tag[p]=0;
    29         }
    30     public:
    31         void build(const int &p,const int &b,const int &e) {
    32             cnt[p]=n-e+1;
    33             if(b==e) return;
    34             const int mid=(b+e)>>1;
    35             build(p _left,b,mid);
    36             build(p _right,mid+1,e);
    37         }
    38         void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x) {
    39             if(b==l&&e==r) {
    40                 cnt[p]+=x;
    41                 tag[p]+=x;
    42                 return;
    43             }
    44             push_down(p);
    45             const int mid=(b+e)>>1;
    46             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x);
    47             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x);
    48             push_up(p);
    49         }
    50         int query(const int &p,const int &b,const int &e,const int &k) {
    51             if(b==e) return cnt[p]>=k?b:b-1;
    52             push_down(p);
    53             const int mid=(b+e)>>1;
    54             return k<=cnt[p _left]?query(p _right,mid+1,e,k):query(p _left,b,mid,k);
    55         }
    56     #undef _left
    57     #undef _right
    58 };
    59 SegmentTree t;
    60 int main() {
    61     scanf("%d%lf",&n,&k);
    62     for(register int i=1;i<=n;i++) d[i]=getint();
    63     std::sort(&d[1],&d[n]+1);
    64     t.build(1,1,n);
    65     for(register int i=n;i;i--) {
    66         pos[std::lower_bound(&d[1],&d[n]+1,d[i])-&d[0]]=i;
    67         size[par[i]=i/k+eps]+=++size[i];
    68     }
    69     for(register int i=1;i<=n;i++) {
    70         if(par[i]&&par[i-1]!=par[i]) {
    71             t.modify(1,1,n,1,ans[par[i]],size[par[i]]-1);
    72         }
    73         ans[i]=pos[std::lower_bound(&d[1],&d[n]+1,d[t.query(1,1,n,size[i])])-&d[0]]++;
    74         printf("%d%c",d[ans[i]]," 
    "[i==n]);
    75         t.modify(1,1,n,1,ans[i],-size[i]);
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    对var和let作用域用闭包的特性做最好的解释
    Js函数作用域
    问题记录
    Git学习
    React-router BrowserRouter导致axios请求时会重复url中的某些字段
    leetcode python 032 识别最长合法括号
    leetcode python 030 Substring with Concatenation of All Words
    n阶楼梯,一次走1,2,3步,求多少种不同走法
    leetcode python 012 hard 合并k个有序链表
    leetcode python 011
  • 原文地址:https://www.cnblogs.com/skylee03/p/8817768.html
Copyright © 2020-2023  润新知