zoukankan      html  css  js  c++  java
  • SDOI2018IIIDX

    /*
    题目转换为  n个节点的一片森林,n个权值,要给每个节点分配一个权值,保证子节点的权值不小于父节点的权值,并且1~n的权值的字典序最大。
    
    考场上的贪心很显然  建立出 树来  将所有数值从大到小排序 然后后序遍历依次填进去  这样就可以处理 互不相同的数据  然后一旦有相同的就会gg
    
    正解
    考虑从前往后贪心  我们把所有的数字按照从大到小排序, 然后从前往后贪心
    
    每个位置贪心找当前能放的最大的,也就是保证子树元素都比改点大, 如果有相同的, 令我们选择在序列中最靠右的,这样才有可能将较大的留给后面的
    
     对于数列构建线段树  令res[i] 表示第i个元素以及他左边 空余的元素有多少个  每次查询在线段树上二分
     
     找到这个元素之后 体会一下他的所有孩子都会比这个元素大  所以res[i - n] 都要减去sz[i]
     
     这个限制 当我们遍历该节点的第一个孩子时  将其去除即可 
    
    
    
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #define M 500010
    #define fa(x) (int) floor((x) / (k))
    #define inf 1000000000
    using namespace std;
    
    int read() {
        int nm = 0, f = 1;
        char c = getchar();
        for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for(; isdigit(c); c  =getchar() ) nm = nm * 10 + c - '0';
        return nm * f;
    }
    int n, res[M << 2], lazy[M << 2], note[M], b[M], sz[M], ans[M], cnt[M];
    double k;
    
    void pushup(int now) {
        res[now] = min(res[now << 1], res[now << 1 | 1]);
    }
    
    void pushdown(int now) {
        if(!lazy[now]) return;
        lazy[now << 1] += lazy[now], res[now << 1] += lazy[now], lazy[now << 1 | 1] += lazy[now], res[now << 1 | 1] += lazy[now];
        lazy[now] = 0;
    }
    
    void build(int l, int r, int now) {
        if(l > r) return;
        if(l == r) {
            res[now] = l;
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, now << 1);
        build(mid + 1, r, now << 1 | 1);
        pushup(now);
    }
    
    void modify(int l, int r, int now, int ln, int rn, int ver) {
        if(l > rn || r < ln) return ;
        if(l >= ln && r <= rn) {
            res[now] += ver;
            lazy[now] += ver;
            return;
        }
        int mid = (l + r) >> 1;
        pushdown(now);
        modify(l, mid, now << 1, ln, rn , ver);
        modify(mid + 1, r, now << 1 | 1, ln, rn,ver);
        pushup(now);
    }
    
    int query(int l, int r, int now, int k) {
        if(l == r) return (res[now] >= k) ?l : l + 1;
        int mid = (l + r) >> 1;
        pushdown(now);
        if(k <= res[now << 1 | 1]) return query(l, mid ,now << 1, k);
        return query(mid + 1, r, now << 1 | 1, k);
    }
    
    int main() {
        n = read();
        cin >> k;
        for(int i = 1; i <= n; i++) note[i] = read(), sz[i] = 1;
        sort(note + 1, note + n + 1, greater<int>() );
        for(int i = n; i >= 1; i--) {
            if(note[i] == note[i + 1]) cnt[i] = cnt[i + 1] + 1;
            else cnt[i] = 0;
            sz[fa(i)] += sz[i];
        }
        build(1, n, 1);
        for(int i = 1; i <= n; i++) {
            if(fa(i) && fa(i) != fa(i - 1)) modify(1, n, 1, ans[fa(i)], n, sz[fa(i)] - 1);
            int op = query(1, n, 1, sz[i]);
            op += cnt[op],cnt[op]++,op -= (cnt[op] - 1),ans[i] = op;
            modify(1, n, 1, op, n, -sz[i]);
        }
        for(int i = 1; i <= n; i++) cout << note[ans[i]] << " ";
        return 0;
    }
  • 相关阅读:
    gjrand 4.0 发布,C语言的伪随机数生成器
    Kite 0.2.0 发布,编程语言
    IBM/DW C++11 标准新特性:Defaulted 和 Deleted 函数
    Apache Solr 3.6.2 发布
    bitmap 内存溢出处理
    Qtractor 0.5.7 发布,多轨音序生成器
    CUBRID Node.js Driver 1.1 发布
    OrientDB 1.3.0 发布,基于文档的数据库
    linux centos 下面httpd支持的svn 服务器端安装
    iptables 1.4.17 发布,Linux防火墙
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/9250671.html
Copyright © 2011-2022 走看看