在鄉下的小路旁種著許多蒲公英,而我們的問題正是與這些蒲公英有關。
為了簡化起見,我們把所有的蒲公英看成乙個長度為 n 的序列a1,a2,…,an,其中ai為乙個正整數,表示第 i 棵蒲公英的種類編號。
而每次詢問乙個區間 [l,r] ,你需要回答區間裡出現次數最多的是哪種蒲公英,如果有若干種蒲公英出現次數相同,則輸出種類編號最小的那個。
第一行兩個整數n,m,表示有 n 株蒲公英,m 次詢問。
接下來一行 n 個空格隔開的整數ai,表示蒲公英的種類。
再接下來 m 行每行兩個整數l0,r0,我們令上次詢問的結果為 x(如果這是第一次詢問,則 x=0)。
令l=(l0+x-1) mod n+1,r=(r0+x-1) mod n+1,如果l>r,則交換l,r。
最終的詢問區間為[l,r]。
輸出 m 行。
每行乙個整數,表示每次詢問的結果。
1≤n≤40000,
1≤m≤50000,
1≤ai≤109
6 3
1 2 3 2 1 2
1 5
3 6
1 5
1
2 1
先離散化+預處理 o(nt + nlongn), t為總共的分塊數, len為塊的大小
當 r - l + 1 >= len * 2 - 1, 則l-r內必有乙個整塊(包含邊界)
1.如果不想麻煩,可以對 r - l + 1 < len * 2 - 1 直接暴力,從 l 到到r,按書上二分方法去查詢在l-r直接a[i]的個數,暴力找答案
2.l為塊左邊界 (l % len == 1),r為右邊界(r % len == 0 || r == n(最後不足一塊)),預處理已經知道答案
3.l為塊左邊界,找到r 所在塊的左邊界 rl,預處理知道答案 l-(lr - 1), 暴力rl - r
3.r為塊右邊界, 同上
4.分別找 rl 和 lr,預處理知道 (lr + 1) - (rl - 1)的答案,暴力l - rl、 rl - r即可
大概複雜度為 o(nt + m *n * log n / t), 求導 t = (m * n * log(n))^ (1/3)
#include #define find(x) ((x - 1) / len + 1)
#define wide(l,r) (r - l + 1)
using namespace std;
const int maxn = 4e4 + 5;
const int maxt = 3130;
int len, t, n, m, a[maxn], b[maxn], f[maxt][maxt], tax[maxn], x;
vectorve[maxn];
void init()
for (int i = 1; i <= t; ++ i, memset(tax, 0, sizeof tax))
if (j % len == 0 || j == n) f[i][find(j)] = mid;}}
}int get(int l, int r, int k)
int work(int cnt, int l, int r, int ll, int rr)
}return cnt;
}int main()
else if (r % len == 0)
else
printf("%d\n", b[x]);
}return 0;
}
分塊 蒲公英
include include include include define maxn 40005 using namespace std int rd return x partition section int a maxn blk maxn sizb int tmplwb maxn 離散化的輔...
Violet 蒲公英 分塊
題解 講道理,關於區間眾數問題應該第乙個就想到分塊,可毒瘤出題人說是線段樹.qaq 考慮查詢的區間 l,r 第一種情況,我們可以考字首和以及遞推來進行預處理,查詢的時候直接呼叫即可。第二種情況,我們開乙個桶,將 2 個端點所在不完整塊進行統計,再用乙個 vector 加上中間完整整塊對這些顏色的貢獻...
Violet 蒲公英(分塊)
即使是分塊也無法簡單的合併兩個塊的資料,所以我們考慮分塊的本質 暴力,直接維護塊合併後的資訊 用 f i j 表示第i塊到第j塊這一段的眾數,那麼接下來就可以只考慮怎麼加入兩頭的數 考慮暴力求眾數的做法 記錄當前的眾數以及所有數的出現次數,如果新加入的數的出現次數大於眾數,那麼它取代原眾數成為新的眾...