• [BZOJ3262]陌上花开


    3262: 陌上花开

    Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 2497  Solved: 1115 [Submit][Status][Discuss]

    Description

    有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

    Input

    第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
    以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

    Output

    包含N行,分别表示评级为0...N-1的每级花的数量。

    Sample Input

    10 3
    3 3 3
    2 3 3
    2 3 1
    3 1 1
    3 1 2
    1 3 1
    1 1 2
    1 2 2
    1 3 2
    1 2 1

    Sample Output

    3
    1
    3
    0
    1
    0
    1
    0
    0
    1

    HINT

    1 <= N <= 100,000, 1 <= K <= 200,000

     
    CDQ分治
    先把相同的花合并到一起,因为如果不合并的话在前面的花统计不到在后面的花
    先保证$a$单调不降
    然后在分治过程中一边以$b$为关键字归并,一边把$c$插入到权值树状数组里
    注意在$b$相同的时候先处理左区间的
    还有树状数组要每次清空,但清空方式一定要是怎么插怎么删
    我第一次写竟然写出了$O(nk)$的复杂度来清空树状数组。。。真是石乐志
    时间复杂度满足关系$T(n)=2T(frac{n}{2})+O(nlogn)$且$T(1)=O(1)$
    根据主定理得到$T(n)=O(nlog^2n)$ 
     
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    char buf[10000000], *ptr = buf - 1;
    inline int readint(){
        int n = 0;
        char ch = *++ptr;
        while(ch < '0' || ch > '9') ch = *++ptr;
        while(ch <= '9' && ch >= '0'){
            n = (n << 1) + (n << 3) + ch - '0';
            ch = *++ptr;
        }
        return n;
    }
    const int maxn = 100000 + 10, maxk = 200000 + 10;
    int n, k;
    int arr[maxk] = {0};
    inline void Update(int w, int s){
        for(; w <= k; w += w & -w) arr[w] += s;
    }
    inline int Query(int w){
        int s = 0;
        for(; w; w -= w & -w) s += arr[w];
        return s; 
    }
    struct Node{
        int a, b, c, id, s;
        Node(){}
        Node(int _a, int _b, int _c, int _id = 0, int _s = 1): a(_a), b(_b), c(_c), id(_id), s(_s){}
    }tp[maxn], no[maxn];
    class cmp{
        public:
            bool operator () (const Node &x, const Node &y){
                return x.a == y.a ? x.b == y.b ? x.c < y.c : x.b < y.b : x.a < y.a;
            }
    };
    int rank[maxn] = {0}, cnt[maxn] = {0};
    void CDQ(int l, int r){
        if(l == r) return;
        int mid = l + r >> 1, ll = l, rr = mid + 1, tcnt = 0;
        CDQ(l, mid); CDQ(mid + 1, r);
        while(ll <= mid && rr <= r){
            if(no[ll].b <= no[rr].b){
                Update(no[ll].c, no[ll].s);
                tp[++tcnt] = no[ll++];
            }
            else{
                rank[no[rr].id] += Query(no[rr].c);
                tp[++tcnt] = no[rr++];
            }
        }
        while(ll <= mid){
            Update(no[ll].c, no[ll].s);
            tp[++tcnt] = no[ll++];
        }
        while(rr <= r){
            rank[no[rr].id] += Query(no[rr].c);
            tp[++tcnt] = no[rr++];
        }
        for(int i = l; i <= mid; i++) Update(no[i].c, -no[i].s);
        for(int i = 1; i <= tcnt; i++) no[l + i - 1] = tp[i];
    }
    int main(){
        fread(buf, sizeof(char), sizeof(buf), stdin);
        int N = readint(); n = 0;
        k = readint();
        tp[0] = Node(0, 0, 0, 0, 0);
        for(int a, b, c, i = 1; i <= N; i++){
            a = readint();
            b = readint();
            c = readint();
            tp[i] = Node(a, b, c);
        }
        sort(tp + 1, tp + N + 1, cmp());
        for(int i = 1; i <= N; i++){
            if(tp[i].a == no[n].a && tp[i].b == no[n].b && tp[i].c == no[n].c) no[n].s++;
            else no[++n] = Node(tp[i].a, tp[i].b, tp[i].c, n);
        }
        CDQ(1, n);
        for(int i = 1; i <= n; i++) cnt[rank[no[i].id] + no[i].s - 1] += no[i].s;
        for(int i = 0; i < N; i++) printf("%d
    ", cnt[i]);
        return 0;
    }
  • 相关阅读:
    CSS基础(二十五)--Background背景之让background-image失效
    CSS基础(二十四)--Background背景之background-image平铺图片堆叠显示
    CSS基础(二十三)--Hover鼠标悬浮变色
    Nginx_安全1
    firewalld防火墙
    shell编程习题
    linux忘记密码
    sed和awk详解
    shell正则表达式
    ssh
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7580651.html
Copyright © 2020-2023  润新知