• Careercup


    2014-05-06 10:18

    题目链接

    原题:

    Given a set of intervals, find the interval which has the maximum number of intersections (not the length of a particular intersection). So if input (1,6) (2,3) (4,11), (1,6) should be returned. Some suggest to use Interval Tree to get this done in O(logn), but I did not understand how to construct and use the Interval Tree after reading its wiki page. Is there any other way to do it? If Interval tree is the only option, please educate me how to construct/use one. Thanks.

    题目:有一堆一维的区间,请判断其中和其他区间相交次数最多的区间是哪一个。比如例子(1, 6)、(2, 3)、(4, 11),(1, 6)和其他两个相交了,所以是相交最多的。另外,这位叫“Guy”的老兄又在秀自己的无知了。说自己的第一想法是用线段树来解题,然后又说自己看了Wiki以后不知道怎么写线段树(既然压根儿不会你提它干嘛)。

    解法:我的第一想法是可以用线段树,不过我不会写线段树,所以我试着用树状数组来解决问题。没想到,还真琢磨出一个来。一种暴力的解法自然是两层循环遍历,统计谁的相交次数最多。如果想把复杂度降低到O(n * log(n)),就得使元素有序。首先要明白一点:当A区间和B区间相交时,A和B的相交次数都要加1。那么,当A和BCD都相交时,A的相交次数直接加3,B、C、D的相交次数都加1。如果直接就这么加,复杂度肯定是平方级别的。但你既然看到“都加1”这种字眼,应该会联想到树状数组。树状数组的一种适用模型,就是给区间加上同一个值,然后查询单个元素,符合这道题的需求。我的代码里实现了一个简单的树状数组类,可以批量修改元素,和查询单个元素。单个操作的时间都是O(log(n))。这样n个区间统计完了以后,可以做到O(n * log(n))。在做相交统计之前,需要保证元素有序,比如按"先X后Y"或者“先Y后X”的顺序给区间排序,这个过程也是O(n * log(n))的。总体时间复杂度为O(n * log(n))。从这题可以看出:出题人不靠谱,下面回帖的答题者也大多不靠谱,有光说思路不写代码的,有分析完全错误的,还有断言时间复杂度不可能低于O(n^2)的。总之,这一题让我对Careercup上的题目质量大失所望。如果像“Guy”这样水平的用户活跃在Careercup上,这网站就完蛋了。如果需要了解树状数组,可以自行百度“树状数组”或者Google“Binary Indexed Tree”。

    代码:

      1 // http://www.careercup.com/question?id=6332750214725632
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <vector>
      5 using namespace std;
      6 
      7 class BinaryIndexedTree {
      8 public:
      9     BinaryIndexedTree(int _n = 1): n(_n) {
     10         v.resize(n + 1);
     11     };
     12     
     13     // add val to all elements from v[1] to v[x]
     14     void addAll(int x, int val) {
     15         while (x >= 1) {
     16             v[x] += val;
     17             x -= lowBit(x);
     18         }
     19     };
     20     
     21     // add val to all elements from v[x] to v[y]
     22     void addInterval(int x, int y, int val) {
     23         if (x > y) {
     24             addInterval(y, x, val);
     25             return;
     26         }
     27         addAll(x - 1, -val);
     28         addAll(y, val);
     29     };
     30     
     31     // return v[x]
     32     int sum(int x) {
     33         int res = 0;
     34         while (x <= n) {
     35             res += v[x];
     36             x += lowBit(x);
     37         }
     38         
     39         return res;
     40     };
     41     
     42     ~BinaryIndexedTree() {
     43         v.clear();
     44     };
     45 private:
     46     int n;
     47     vector<int> v;
     48     
     49     int lowBit(int x) {
     50         return x & -x;
     51     };
     52 };
     53 
     54 struct Interval {
     55     int start;
     56     int end;
     57     Interval(int _start = 0, int _end = 0): start(_start), end(_end) {};
     58     
     59     bool operator < (const Interval &other) {
     60         if (start != other.start) {
     61             return start < other.start;
     62         } else {
     63             return end < other.end;
     64         }
     65     };
     66 
     67     friend ostream& operator << (ostream &cout, const Interval &i) {
     68         cout << '(' << i.start << ',' << i.end << ')';
     69         return cout;
     70     };
     71 };
     72 
     73 Interval solve(vector<Interval> &v)
     74 {
     75     int n = (int)v.size();
     76     
     77     if (n == 0) {
     78         return Interval(0, 0);
     79     } else if (n == 1) {
     80         return v[0];
     81     }
     82     
     83     sort(v.begin(), v.end());
     84     BinaryIndexedTree bit(n);
     85     
     86     int i, j;
     87     int ll, rr, mm;
     88     for (i = 0; i < n - 1; ++i) {
     89         if (v[i + 1].start >= v[i].end) {
     90             // no overlapping
     91             continue;
     92         }
     93         
     94         if (v[n - 1].start < v[i].end) {
     95             // all overlapped
     96             j = n - 1;
     97         } else {
     98             ll = i + 1;
     99             rr = n - 1;
    100             while (rr - ll > 1) {
    101                 mm = (ll + rr) / 2;
    102                 if (v[mm].start < v[i].end) {
    103                     ll = mm;
    104                 } else {
    105                     rr = mm;
    106                 }
    107             }
    108             j = ll;
    109         }
    110         // from [i + 1, j], they all overlap with v[i].
    111         bit.addInterval(i + 2, j + 1, 1);
    112         bit.addInterval(i + 1, i + 1, j - i);
    113     }
    114     
    115     int ri;
    116     int res, mres;
    117     
    118     ri = 0;
    119     mres = bit.sum(1);
    120     for (i = 1; i < n; ++i) {
    121         res = bit.sum(i + 1);
    122         ri = res > mres ? i : ri;
    123     }
    124     
    125     return v[ri];
    126 }
    127 
    128 int main()
    129 {
    130     int i;
    131     int n;
    132     vector<Interval> v;
    133     Interval res;
    134     
    135     while (cin >> n && n > 0) {
    136         v.resize(n);
    137         for (i = 0; i < n; ++i) {
    138             cin >> v[i].start >> v[i].end;
    139         }
    140         res = solve(v);
    141         cout << res << endl;
    142         v.clear();
    143     }
    144     
    145     return 0;
    146 }
    147 
    148 /*
    149 // A simple test for the BIT above.
    150 int main()
    151 {
    152     string cmd;
    153     int n;
    154     BinaryIndexedTree *bit = nullptr;
    155     int x, y, val;
    156     int i;
    157     
    158     while (cin >> n && n > 0) {
    159         bit = new BinaryIndexedTree(n);
    160         while (true) {
    161             for (i = 1; i <= n; ++i) {
    162                 cout << bit->sum(i) << ' ';
    163             }
    164             cout << endl;
    165             cin >> cmd;
    166             if (cmd == "e") {
    167                 break;
    168             } else if (cmd == "a") {
    169                 cin >> x >> val;
    170                 bit->addAll(x, val);
    171             } else if (cmd == "ai") {
    172                 cin >> x >> y >> val;
    173                 bit->addInterval(x, y, val);
    174             }
    175         }
    176         delete bit;
    177         bit = nullptr;
    178     }
    179     
    180     return 0;
    181 }
    182 */
  • 相关阅读:
    左侧列固定的表格
    百度地图上添加多个标记,标记上添加信息展示窗口、跳转到导航界面
    vue-cli4版本解决eslint问题
    使用脚手架搭建项目
    正则表达式学习
    函数参数:
    装饰器(重点)
    列表生成式、生成器、迭代器
    logging 日志模块
    json 、 pickle 、shelve序列化
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3711020.html
Copyright © 2020-2023  润新知