[Violet]蒲公英
阿新 • • 發佈:2021-09-08
[Violet]蒲公英
強制線上求區間眾數。
思路
與一些分塊題不同,本題並沒有在塊內插入其他東西進行維護,最樸素的分塊。類似【作詩】的預處理,預先處理出每個數出現的塊字尾和(字首和應該也沒有問題),以及塊間的眾數。對於[l,r]位於的塊是挨著或在同一塊的情況,直接暴力處理(挨著的不太好處理),其餘的按照分塊的正常思路進行。顯然,[l,r]的眾數一定是整塊的眾數或者散塊中出現的數。注意細節:要輸出的是離散化前的編號,以及這裡是字尾和,別還原成了字首和。
程式碼
memset
又一次拖慢近5倍。
艱難困苦,玉汝於成inline void INIT() { len = sqrt(n);t = n / len; for(int i = 1;i <= t;i++){ L[i] = (i - 1) * len + 1; R[i] = i * len; } R[t] = n; block[n + 1] = n + 1; for(int i = 1;i <= t;i++) for(int j = L[i];j <= R[i];j++) block[j] = i; for(int i = 1;i <= t;i++){ int mx = 0; for(int j = L[i];j <= n;j++){ cnt[i][a[j]]++; if(cnt[i][mx] < cnt[i][a[j]] || (cnt[i][mx] == cnt[i][a[j]] && a[j] < mx)) mx = a[j]; if(block[j] != block[j + 1]) res[i][block[j]] = mx; } } } signed main() { n = read();m = read(); for(int i = 1;i <= n;i++) a[i] = read(),b[i] = a[i]; sort(b + 1,b + 1 + n); tot = unique(b + 1,b + 1 + n) - b - 1; for(int i = 1;i <= n;i++) a[i] = lower_bound(b + 1,b + 1 + tot,a[i]) - b; INIT(); while(m--) { LL l,r;ans = 0; scanf("%lld%lld",&l,&r); l = (l + lstans - 1) % n + 1,r = (r + lstans - 1) % n + 1; if(l > r) swap(l,r); if(block[l] + 1 >= block[r]){ for(int i = l;i <= r;i++){ num[a[i]]++; if(num[ans] < num[a[i]] || (num[ans] == num[a[i]] && a[i] < ans)) ans = a[i]; } lstans = b[ans]; write(lstans);putchar('\n'); for(int i = l;i <= r;i++) num[a[i]]--; continue; } ans = res[block[l] + 1][block[r] - 1]; int all = cnt[block[l] + 1][ans] - cnt[block[r]][ans]; for(int i = l;i <= R[block[l]];i++){ num[a[i]]++; if(num[ans] + all < num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] || (num[ans] + all == num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] && a[i] < ans)) ans = a[i],all = cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]]; } for(int i = L[block[r]];i <= r;i++){ num[a[i]]++; if(num[ans] + all < num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] || (num[ans] + all == num[a[i]] + cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]] && a[i] < ans)) ans = a[i],all = cnt[block[l] + 1][a[i]] - cnt[block[r]][a[i]]; } lstans = b[ans]; write(lstans);putchar('\n'); for(int i = l;i <= R[block[l]];i++) num[a[i]]--; for(int i = L[block[r]];i <= r;i++) num[a[i]]--; } return 0; }