Topcoder SRM 675 Div1 500Pts LimitedMemorySeries1(分塊)
阿新 • • 發佈:2018-02-12
tor bits fin get pre n) ted 多少 top
題意 給定一個長度不超過$5*10^{6}$的數列和不超過$100$個詢問,每次詢問這個數列第$k$小的數,返回所有詢問的和
內存限制很小,小到不能存下這個數列。(數列以種子的形式給出)
時限$10s$,內存限制$13MB$
我自己YY的分治縮小答案上下界範圍第三個樣例要跑$90s$左右,果斷放棄
根據題目給出的條件我們知道每一個數的範圍都在$[0, 10^{9}+6]$裏。
那麽我們開一個大小為$32000$的數組,把$[0, 10^{9}+6]$分成$32000$個大小相同的塊。
然後先遍歷整個數列,求出每個塊中有多少個數。
在詢問的時候先確定當前要查詢的那個數在哪個塊裏。
確定了那個塊的位置之後,我們再遍歷一遍數列,找到那些在這個塊裏的數,再把精確值求出來。
時間復雜度$O(qn)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 32000; int block[N], c[N]; class LimitedMemorySeries1 { public: LL getSum(int n, int x0, int a, int b, vector<int> query){ memset(block, 0, sizeof block); int x = x0; rep(i, 0, n - 1){ block[x / N]++; x = (int)((x * (LL)a + b) % 1000000007); } LL sum = 0; for (auto q : query){ int acum = 0; int p = -1; int before = 0; rep(i, 0, N - 1){ if (acum <= q && q < acum + block[i]){ p = i; before = acum; break; } acum += block[i]; } memset(c, 0, sizeof c); x = x0; for (int i = 0; i < n; i++){ if (p * N <= x && x < (p + 1) * N){ c[x - p * N]++; } x = (int)((x * (LL)a + b) % 1000000007); } acum = before; int r = -1; for (int i = 0; i < N; i++){ if (acum <= q && q < acum + c[i]){ r = p * N + i; break; } acum += c[i]; } sum += r; } return sum; } };
Topcoder SRM 675 Div1 500Pts LimitedMemorySeries1(分塊)