【bzoj2724】[Violet 6]蒲公英

来源:互联网 发布:又污又有内涵的网络词 编辑:程序博客网 时间:2024/05/17 03:19

  坑了好久的区间众数……
  思路是分块。
  设块的大小为l,有x个块
  预处理第i个块和第j个块之间的众数和出现次数,这是O(xn)的。
  对于每个询问[l,r],如果l和r在同一个块里面,就暴力查询,这是O(l)的;如果不在同一个块,则先以预处理的信息得到中间连续的块的答案,然后再在最两边的两个块暴力查询每个数在中间出现的次数,然后更新答案。偷懒没多想,写了个主席树,所以是O(llogn)的。
  于是总的复杂度是O(xn+mllogn)
  稍微计算+对拍,取l=100左右的时候可以在时限内跑完。
  

#include <bits/stdc++.h>#define rep(i,a,b) for(int i=a,_=b;i<=_;i++)#define per(i,a,b) for(int i=a,_=b;i>=_;i--)#define maxn 50007#define maxb (742)typedef int arr[maxn];typedef int blk[maxb];typedef int seg[maxn * 20];inline int rd() {    char c = getchar();    while (!isdigit(c)) c = getchar() ; int x = c - '0';    while (isdigit(c = getchar())) x = x * 10 + c - '0';    return x;}int BLOCKS;seg sz , lc , rc;arr belong , cnt , a , h , rt;blk st , ed , ans[maxb] , rec[maxb];int n_tot , tot , n , m;void update(int pr , int&nr , int l , int r , int v) {    if (!nr) nr = ++ n_tot;    sz[nr] = sz[pr] + 1;    if (l == r) return;    int m = (l + r) >> 1;    if (v <= m)        rc[nr] = rc[pr] , update(lc[pr] , lc[nr] , l , m , v);    else        lc[nr] = lc[pr] , update(rc[pr] , rc[nr] , m + 1 , r , v);}int query(int pr , int nr , int l , int r , int v) {    while (l < r) {        int m = (l + r) >> 1;        if (v <= m)            nr = lc[nr] , pr = lc[pr] , r = m;        else            nr = rc[nr] , pr = rc[pr] , l = m + 1;    }    return sz[nr] - sz[pr];}void input() {    n = rd() , m = rd();    rep (i , 1 , n) h[i] = a[i] = rd();}void discrete() {    std::sort(h + 1 , h + n + 1);    rep (i , 1 , n) a[i] = std::lower_bound(h + 1 , h + n + 1 , a[i]) - h;    rep (i , 1 , n) update(rt[i - 1] , rt[i] , 1 , n , a[i]);}void init_block() {    BLOCKS = 101;    rep (i , 1 , n)        belong[i] = (i - 1) / BLOCKS + 1;    tot = belong[n];    rep (i , 1 , tot)        st[i] = (i - 1) * BLOCKS + 1 , ed[i] = i * BLOCKS;    rep (i , 1 , tot) {        int mx = 0 , t = 0;        rep (j , st[i] , n) {            cnt[a[j]] ++;            if (cnt[a[j]] > mx || (cnt[a[j]] == mx && a[j] < t))                mx = cnt[a[j]] , t = a[j];            ans[i][belong[j]] = t;            rec[i][belong[j]] = cnt[t];        }        rep (j , st[i] , n)            cnt[a[j]] = 0;    }}int get_ans(int l , int r) {    int mx = 0 , t;    if (belong[l] == belong[r]) {        rep (i , l , r) cnt[a[i]] = 0;        rep (i , l , r) cnt[a[i]] ++;        rep (i , l , r) if (cnt[a[i]] > mx || (cnt[a[i]] == mx && a[i] < t))            mx = cnt[a[i]] , t = a[i];    } else {        if (belong[l] - 1 < belong[r])            mx = rec[belong[l] + 1][belong[r] - 1] , t = ans[belong[l] + 1][belong[r] - 1];        rep (i , l , ed[belong[l]]) {            int c = query(rt[l - 1] , rt[r] , 1 , n , a[i]);            if (c > mx || (c == mx && a[i] < t))                t = a[i] , mx = c;        }        rep (i , st[belong[r]] , r) {            int c = query(rt[l - 1] , rt[r] , 1 , n , a[i]);            if (c > mx || (c == mx && a[i] < t))                t = a[i] , mx = c;        }    }    return t;}void solve() {    discrete();    init_block();    int ans = 0;    #ifndef ONLINE_JUDGE        freopen("data.out" , "w" , stdout);    #endif    rep (i , 1 , m) {        int l = (rd() + ans - 1) % n + 1;        int r = (rd() + ans - 1) % n + 1;        if (l > r) std::swap(l , r);        ans = h[get_ans(l , r)];        printf("%d\n" , ans);    }}int main() {    #ifndef ONLINE_JUDGE        freopen("data.txt" , "r" , stdin);    #endif    input();    solve();    return 0;}
0 0
原创粉丝点击