如何在不到1秒的时间内运行此代码?

时间:2015-08-21 21:42:40

标签: c++ search binary

如何在不超出时间限制的情况下解决此问题

http://codeforces.com/problemset/problem/474/B

我尝试将所有范围放在2D矢量中,然后使用二分搜索查找所需的索引,但似乎fn BS()中的循环需要花费很多时间才能执行,因为矢量的大小可以是10 ^ 6。

这是我的代码:

#include <iostream>
#include <vector>
using namespace std;

int Search(vector <vector<int> > a,int key){
    int start = 0;
    int end = a.size() - 1;
    while (start <= end){
        int mid = start + (end - start) / 2;
        if (a[mid][0] > key && a[mid][1] > key){
            end = mid - 1;
        }
        else if (a[mid][0] < key && a[mid][1] < key){
            start = mid + 1;
        }
        else {
            return mid;
        }
    }

    return -1;
}
vector <int> BS(vector <vector <int> > v, vector<int> keys){
    int j = 0;
    vector <int> piles;
    for (int i = 0; i < keys.size(); i++){
        piles.push_back(Search(v, keys[i])+1);
    }
    return piles;
}
vector < vector<int> > Range(vector<int> v){
    vector < vector<int> > ranges(v.size());
    int sum1 = 1;
    int sum2 = v[0];
    for (int i = 0; i < v.size(); i++){
        if (i == 0){
            ranges[i].push_back(sum1);
            ranges[i].push_back(v[i]);
            sum1 += v[i];
        }
        else{
            ranges[i].push_back(sum1);
            sum2 += v[i];
            ranges[i].push_back(sum2);
            sum1 += v[i];
        }
    }
    return ranges;
}

int main(){
    int n, m;
    cin >> n;
    vector <int> a, q;

    vector < vector <int> > v;
    for (int i = 0; i < n; i++){
        int k;
        cin >> k;
        a.push_back(k);
    }
    cin >> m;
    for (int i = 0; i < m; i++){
        int l;
        cin >> l;
        q.push_back(l);
    }

    v = Range(a);

    vector <int> jucy = BS(v, q);


    for (int i = 0; i < jucy.size(); i++){
        cout << jucy[i] << endl;
    }




}

2 个答案:

答案 0 :(得分:6)

事实上,我认为你根本不需要2D矢量,你只需要1D。例如,女巫看起来像[2,9,12,16,25],每堆的上限,你可以很容易地构建这个。然后对于每个多汁的蠕虫,你以这种方式进行二元搜索,它返回的索引的值大于或等于你要查找的值。您从搜索中获得的索引是您正在寻找的堆。

一些伪代码:

const int max = 1000;
struct pair *ptr = malloc(sizeof(pair) * max); // allocated 1000 pairs
free(ptr); // when the amount of memory is not needed anymore

你得到的索引是第一个值等于或大于q,所以堆在哪里是q。

和C ++代码:

A[n] - vector of upper bounds

A[0] = a0

For each 0<i<=n A[i]=A[i-1]+ai

For each q do std lower_bound on A looking for q,

您必须为距离添加+1,因为桩的编号为1.为示例工作,看起来非常快。

答案 1 :(得分:2)

最明显的优化机会是,而不是使用vector<vector<int>>使用vector<int>并手动将2D索引调整为1D。您可以编写一个简单的包装类来为您执行此操作。

更快的原因是所有内存将被分配为单个连续单元。如果你有一个向量向量,那么每一行都会在其他地方,你会有很多缓存未命中。

这是一个代码示例:

struct 2D_Vector {
  std::vector<int> me_;
  int ncols_;
  2D_Vector(int nrows, int ncols) : me(nrows * ncols), ncols_(ncols) {}

  int & get(int y, int x) { return me_[y * ncols_ + x]; }
  const int & get(int y, int x) const { return me_[y * ncols_ + x]; }

  ...
};

如果你预先分配它需要的所有空间,那么它应该非常有效地使用内存。

此外,通过值而不是通过引用传递大型函数参数是非常浪费的,因为它会导致不必要的副本被制作和销毁。 (就像WhozCraig指出的那样。)