Rintaro @ 2019-03-15 21:09:06
lyd书上的第二种做法 复杂度O(NT+MN/T*logN),取T = sqrt(NlogN) 但我在实际实现时,分块长度按这么取就T了,我调参的时候,发现长度取到100以下反而能快。。取到50以下就A掉了此题,也许是我实现错了?
#include <iostream>
#include <cstdio>
#include <climits>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <cmath>
#define readint(x) scanf("%d",&(x))
#define putint(x) printf("%d\n",(x))
#define lowbit(x) ((x)&(-(x)))
#define mp(x,y) make_pair((x),(y))
#define lint long long
#define rint register int
#define ldob long double
using namespace std;
const int maxn = 50000 + 10;
const int maxlen = 3000;
int n, m, len, t;
int arr[maxn], preans[maxlen][maxlen][2];
int cnt[maxn], htval[maxn];
int ht[maxn], tot = 0;
vector<int> mem[maxn];
// 1 3 3 5 6 7 9
inline int ask(int val, int l, int r){ // 返回L,R范围内有多少个val
int i = lower_bound(mem[val].begin(),mem[val].end(),l) - mem[val].begin(),
j = upper_bound(mem[val].begin(),mem[val].end(),r) - mem[val].begin() - 1;
return j - i + 1;
}
// 计算x属于哪段
inline int eco(int x){
return (x-1) / len + 1;
}
int main(){
// freopen("testdata.in","r",stdin);
// freopen("ans.out","w",stdout);
readint(n), readint(m);
len = min((int)sqrt(n),20), t = ceil((double)n/len);
for(rint i=1; i<=n; i++) readint(arr[i]), ht[i] = arr[i];
sort(ht+1,ht+n+1);
tot = unique(ht+1,ht+n+1) - (ht+1);
for(rint i=1; i<=n; i++) {
int val = arr[i];
arr[i] = lower_bound(ht+1,ht+tot+1,val) - ht;
htval[arr[i]] = val;
mem[arr[i]].push_back(i);
}
for(rint lt=1; lt<t; lt++){ // 枚举左端点
int nowans = 0;
memset(cnt,0,sizeof(cnt));
for(rint j=(lt-1)*len+1; j<=n; j++){
cnt[arr[j]]++;
if(cnt[arr[j]] > cnt[nowans] || (cnt[arr[j]] == cnt[nowans] && htval[nowans] > htval[arr[j]])) nowans = arr[j]; // >保证编号最小
if(j % len == 0) preans[lt][j/len][0] = nowans, preans[lt][j/len][1] = cnt[nowans];
if(j == n) preans[lt][t][0] = nowans, preans[lt][t][1] = cnt[nowans];
}
}
memset(cnt,0,sizeof(cnt));
int l, r, x = 0;
while(m--){
scanf("%d %d",&l,&r);
l = (l+x-1) % n + 1, r = (r+x-1) % n + 1;
if(l > r) swap(l,r);
int lt = eco(l), rt = eco(r), ans = 0, nmax = 0;
if(rt - lt <= 1){
for(rint i=l; i<=r; i++) cnt[arr[i]]++;
for(rint i=l; i<=r; i++) {
if(cnt[arr[i]] > nmax || (cnt[arr[i]] == nmax && htval[ans] > htval[arr[i]])){
ans = arr[i], nmax = cnt[arr[i]];
}
}
for(rint i=l; i<=r; i++) cnt[arr[i]]--;
}else {
ans = preans[lt+1][rt-1][0], nmax = preans[lt+1][rt-1][1];
for(rint i=l; i<=lt*len; i++) {
int lans = ask(arr[i],l,r);
if(nmax < lans || (nmax == lans && htval[ans] > htval[arr[i]])) ans = arr[i], nmax = lans; //输出编号最小
}
for(rint i=(rt-1)*len+1; i<=r; i++){
int rans = ask(arr[i],l,r);
if(nmax < rans || (nmax == rans && htval[ans] > htval[arr[i]])) ans = arr[i], nmax = rans;
}
}
x = htval[ans];
printf("%d\n",x);
}
return 0;
}
/*
for(rint i=1; i<=n; i++){
readint(arr[i]);
if(htdex.find(arr[i]) == htdex.end()) { //不存在
htdex[arr[i]] = i;
htval[i] = arr[i];
}
arr[i] = htdex[arr[i]];
mem[arr[i]].push_back(i); // 存下标 vector从0开始
}
*/
by 花里心爱 @ 2019-03-15 21:48:22
这似乎是每个操作常数不相等带来的问题?qwq
by noip @ 2019-03-16 08:05:35
写线性空间的nsqrtn做法啊
多好啊
by shadowice1984 @ 2019-03-28 21:00:33
写线性空间的nsqrtn做法啊
多好啊
都9120年了区间众数还要带log的吗……