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;
    }
  • 相关阅读:
    自定义View之实现流行的底部菜单栏中间突起:高仿“咸鱼APP”的底部菜单
    android获取内置和外置SD卡路径
    Android Environment.getExternalStorageDirectory() 获取的是内部存储还是外部存储?
    bitmap过大无法显示图片的问题
    Android Notification的使用
    Android Device Monitor 文件管理的常见问题
    BroadcastReceiver广播相关
    Android Studio 设置代码提示和代码自动补全快捷键--Eclipse 风格
    Android Studio com.android.support:percent 导入错误
    约束布局constraint-layout导入失败的解决方案
  • 原文地址:https://www.cnblogs.com/Lyush/p/2643363.html
Copyright © 2011-2022 走看看