莫隊演算法
阿新 • • 發佈:2020-07-21
1.不帶修改的普通莫隊演算法
#pragma GCC optimize(3) #pragma GCC optimize(2) #include <iostream> #include <string> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <functional> #include <vector> #include <map> #include<set> #include <stack> #include <fstream> #include <sstream> #include <unordered_map> #define FT(a, b) memset(a, b, sizeof(a)) #define FAT(a) memset(a, 0, sizeof(a)) using namespace std; typedef unsigned long long ll; const int N = 5e2 + 10; const int M = 1e6 + 10; const intINF = 0x3f3f3f3f; const ll mod = 1e9 + 7; int n, m, k, x, y, s, t; int a[M], cnt[M], belong[M], ans[M]; struct query { int l, r, id; bool operator<(const query &b) const { return (belong[l] ^ belong[b.l]) ? belong[l] < belong[b.l] : ((belong[l] & 1) ? r < b.r : r > b.r);//奇偶性排序,對於左端點在同一奇數塊的區間,右端點按升序排列,反之降序。 //要原理便是右指標跳完奇數塊往回跳時在同一個方向能順路把偶數塊跳完,然後跳完這個偶數塊又能順帶把下一個奇數塊跳完。 //理論上主演算法執行時間減半,實際情況有所偏差 } } q[M]; void init() { int size = sqrt(n);//分塊大小 int bnum = ceil((double)n / size);//分塊個數 for (int i = 1; i <= bnum; ++i) for (int j = (i - 1) * size + 1; j <= i * size; ++j) { belong[j] = i; } FAT(cnt); } void work() { int l = 1, r = 0, now = 0; for (int i = 0; i < m; ++i) { int ql = q[i].l, qr = q[i].r; while (l < ql) now -= --cnt[a[l++]] == 0; while (l > ql) now += cnt[a[--l]]++ == 0; while (r < qr) now += cnt[a[++r]]++ == 0; while (r > qr) now -= --cnt[a[r--]] == 0; //移動指標的常數壓縮 ans[q[i].id] = now; } } void slove() { scanf("%d", &n); init(); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); scanf("%d", &m); for (int i = 0; i < m; ++i) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i; sort(q, q + m); work(); for (int i = 0; i < m; ++i) printf("%d\n", ans[i]); } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/wjy/code/in.txt", "r", stdin); // freopen("/home/wjy/桌面/t12.out", "w", stdout); // freopen("/home/wjy/code/in.txt", "r", stdin); #endif ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int T = 1; // scanf("%d",&T); // cin >> T; // time_t begin, end; // begin = clock(); while (T--) { slove(); // double ret = double(end - begin) / CLOCKS_PER_SEC; // end = clock(); // double ret = double(end - begin) / CLOCKS_PER_SEC; // cout << "runtime: " << ret << endl; } return 0; }