日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【分块】区间众数(金牌导航 分块-1)

發布時間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【分块】区间众数(金牌导航 分块-1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

區間眾數

金牌導航 分塊-1

題目大意

給出一個數列,和若干詢問,每個詢問讓你求一個區間內的眾數

輸入樣例

6 3 1 2 3 2 1 2 1 5 3 6 1 5

輸出樣例

1 2 1

數據范圍

1?N?4×104,1?M?5×104,1?ai?1091\leqslant N \leqslant 4\times 10^4,1\leqslant M \leqslant 5\times 10^4,1\leqslant a_i \leqslant 10^91?N?4×104,1?M?5×104,1?ai??109

解題思路

對于求區間眾數,線段樹不易維護
考慮分塊
先對數列a離散化
然后枚舉一遍數列a,求出numi,jnum_{i,j}numi,j?(前i個塊中j顏色出現的次數),時間O(nn)O(n\sqrt{n})O(nn?)
然后求一段連續塊的眾數,先枚舉左段的塊,然后暴力搜右節點,時間O(nn)O(n\sqrt{n})O(nn?)
然后對于每次查詢,暴力枚舉不在整一個塊的數

代碼

#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 40010 #define QN 210 using namespace std; int n, m, x, y, g, L, R, nn, nm, a[N], b[N], p[N], f[QN][QN], num[QN][N]; int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i){scanf("%d", &a[i]);b[i] = a[i];}sort(b + 1, b + 1 + n);g = unique(b + 1, b + 1 + n) - b - 1;for (int i = 1; i <= n; ++i)a[i] = lower_bound(b + 1, b + 1 + g, a[i]) - b;nn = sqrt(n);g = 0;nm = n / nn + (n % nn? 1: 0);for (int i = 1; i <= n; ++i){p[a[i]]++;if (i % nn == 0){g++;for (int j = 1; j <= n; ++j)num[g][j] = p[j];}}if (g < nm){for (int j = 1; j <= n; ++j)num[n / nn + 1][j] = p[j];}for (int i = 1; i <= nm; ++i){g = 0;memset(p, 0, sizeof(p));for (int j = (i - 1) * nn + 1; j <= n; ++j){p[a[j]]++;if (p[a[j]] > p[g] || p[a[j]] == p[g] && a[j] < g) g = a[j];if (j % nn == 0) f[i][j / nn] = g;}}memset(p, 0, sizeof(p));g = 0;while(m--){scanf("%d%d", &x, &y);x = (x + b[g] - 1) % n + 1;y = (y + b[g] - 1) % n + 1;if (x > y) swap(x, y);L = (x + nn - 2) / nn + 1;R = y / nn;if (L > R)//沒包含任意一個整的塊直接暴力{g = 0;for (int i = x; i <= y; ++i){p[a[i]]++;if (p[a[i]] > p[g] || p[a[i]] == p[g] && a[i] < g)g = a[i];}for (int i = x; i <= y; ++i)p[a[i]]--;printf("%d\n", b[g]);continue;}g = f[L][R];for (int i = x; i <= min((L - 1) * nn, n); ++i){p[a[i]]++;int X = p[a[i]] + num[R][a[i]] - num[L - 1][a[i]];//加上整的塊里面的int Y = p[g] + num[R][g] - num[L - 1][g];if (X > Y || X == Y && a[i] < g)g = a[i];}for (int i = max(R * nn + 1, 1); i <= y; ++i){p[a[i]]++;int X = p[a[i]] + num[R][a[i]] - num[L - 1][a[i]];int Y = p[g] + num[R][g] - num[L - 1][g];if (X > Y || X == Y && a[i] < g)g = a[i];}for (int i = x; i <= min((L - 1) * nn, n); ++i)//把原來的清掉,不然要O(n),會超時p[a[i]]--;for (int i = max(R * nn + 1, 1); i <= y; ++i)p[a[i]]--;printf("%d\n", b[g]);}return 0; }

總結

以上是生活随笔為你收集整理的【分块】区间众数(金牌导航 分块-1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。