zoukankan      html  css  js  c++  java
  • HDU时间挑战 树状数组

    这题好像是POJ的一道原题... 首先这题我们能够确定如果一条线段被另外一条线段所包含的话,那么那条包含它的线段的左端点一定小于或者等于这个线段。于是我们按照左端点从小到大排序,左端点相同按照右端点从大到小排序,这样就能够保证所有包含第i条线段的线段一定在前面得到了更新。

    接着我们就直接要求前面线段的右区间大于改线段,由于用的树状数组,所以用一个数减去这个右端点,所以该右端点就越靠近左边,所以也就能使上树状数组了,需要注意的当两条线段的属性完全一样时,我们要直接把前面的答案赋值给后面的线段,然后再去更新。

    代码如下:

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <map>
    using namespace std;
    
    int N, c[400005], ret[200005], idx;
    
    map<int,int>mp;
    
    struct Node
    {
        int l, r, NO;
        bool operator < (Node temp) const
        {
            if (l != temp.l) return l < temp.l;
            return r > temp.r;
        }
    }e[200005];
    
    struct High
    {
        int h;
        bool operator < (High temp) const
        {
            return h < temp.h;
        } 
        bool operator == (High temp) const
        {
            return h == temp.h;
        }
    }H[400005];
    
    int lowbit(int x)
    {
        return x & -x;
    }
    
    void add(int x, int val)
    {
        for (int i = x; i <= 400000; i += lowbit(i)) {
            c[i] += val;
        }
    }
    
    int sum(int x)
    {
        int ret = 0;
        for (int i = x; i > 0; i -= lowbit(i)) {
            ret += c[i];
        }
        return ret;
    }
    
    int main()
    {
        while (scanf("%d", &N) == 1) {
            memset(c, 0, sizeof (c));
            memset(ret, 0, sizeof (ret));
            mp.clear();
            idx = -1;
            for (int i = 0; i < N; ++i) {
                scanf("%d %d", &e[i].l, &e[i].r);
                e[i].NO = i;
                H[++idx].h = e[i].l, H[++idx].h = e[i].r;
            }
            sort(H, H+idx+1);
            idx = unique(H, H+idx+1)-H;
            for (int i = 0; i < idx; ++i) {
                mp[H[i].h] = idx - i;
            }
            sort(e, e + N);
            for (int i = 0; i < N; ++i) {
                int pos = mp[e[i].r];
                if (i > 0 && e[i].l == e[i-1].l) {
                    if (e[i].r == e[i-1].r) {
                        ret[e[i].NO] = ret[e[i-1].NO];
                    }
                    else {
                        ret[e[i].NO] = sum(pos);
                    }
                }
                else if (i > 0 && e[i].l > e[i-1].l) {
                    ret[e[i].NO] = sum(pos);
                }
                else {
                    ret[e[i].NO] = 0;
                }
                add( pos, 1 );
            }
            for (int i = 0; i < N; ++i) {
                if (i == 0) {
                    printf("%d", ret[i]);
                }
                else {
                    printf(" %d", ret[i]);
                }
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    蓝桥杯_基础_杨辉三角
    蓝桥杯_基础_数组特征
    蓝桥杯_基础_美丽的图形
    脉象
    词根汇总
    蓝桥杯 入门训练 Fibonacci数列 解析
    制作tomcat重启.bat文件
    day23(023-递归练习)
    day27(027-反射&JDK新特性)
    day25(025-多线程(下)&GUI)
  • 原文地址:https://www.cnblogs.com/Lyush/p/2643363.html
Copyright © 2011-2022 走看看