zoukankan      html  css  js  c++  java
  • bzoj2724 [Violet 6]蒲公英

    2724: [Violet 6]蒲公英

    Time Limit: 40 Sec  Memory Limit: 512 MB
    Submit: 2706  Solved: 950
    [Submit][Status][Discuss]

    Description

    Input

    修正一下

    l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

    Output

    Sample Input

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

    Sample Output

    1
    2
    1

    HINT

    n <= 40000, m <= 50000

    Source

    Vani原创

    分析:经典题.

       如果没有强制在线,就可以用莫队算法解决了. 能够利用莫队算法这一事实提供了一个思路:根号算法.

       还有哪些根号算法呢?可以分块!首先有一个结论:区间[l,r]的众数一定是[l,r]整块的众数或者是不在整块的数. 一个想法就是预处理出f数组,f[i][j]表示第i块到第j块的众数.  枚举左端点,维护一个桶就能够预处理出来了.  

       怎么求区间[l,r]出现了多少次a呢? 前缀和?空间不够. 一个可行的方法是对块进行前缀和,然后枚举不在整块内的元素,用一个桶维护每个值出现的次数.  有一个更好的方法:开一个vector数组,第i个vector存着权值为i的下标. 每次upper_bound,lower_bound找下标正好在[l,r]的个数就好了. 

    #include <vector>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    const ll maxn = 50010;
    ll n,m,a[maxn],b[maxn],tot[maxn],cnt,cntt,lastans;
    ll pos[maxn],L[maxn],R[maxn],block,f[1010][1010];
    vector <ll>e[maxn];
    
    void pre(ll x)
    {
        ll ans = 0,tott = 0;
        memset(tot,0,sizeof(tot));
        for (ll i = L[x]; i <= n; i++)
        {
            tot[a[i]]++;
            if (tot[a[i]] > tott || (tot[a[i]] == tott && b[ans] > b[a[i]]))
            {
                ans = a[i];
                tott = tot[a[i]];
            }
            f[x][pos[i]] = ans;
        }
    }
    
    ll query(ll l,ll r)
    {
        if (pos[l] == pos[r])
        {
            ll ans = 0;
            cntt = 0;
            for (ll i = l; i <= r; i++)
            {
                ll temp = upper_bound(e[a[i]].begin(),e[a[i]].end(),r) - lower_bound(e[a[i]].begin(),e[a[i]].end(),l);
                if (temp > cntt || (temp == cntt && b[a[i]] < b[ans]))
                {
                    ans = a[i];
                    cntt = temp;
                }
            }
            return ans;
        }
        ll temp = f[pos[l] + 1][pos[r] - 1];
        ll cntt = upper_bound(e[temp].begin(),e[temp].end(),r) - lower_bound(e[temp].begin(),e[temp].end(),l);
        for (ll i = l; i <= R[pos[l]]; i++)
        {
            ll tmp = upper_bound(e[a[i]].begin(),e[a[i]].end(),r) - lower_bound(e[a[i]].begin(),e[a[i]].end(),l);
            if (tmp > cntt || (tmp == cntt && a[i] < temp))
            {
                temp = a[i];
                cntt = tmp;
            }
        }
        for (ll i = L[pos[r]]; i <= r; i++)
        {
            ll tmp = upper_bound(e[a[i]].begin(),e[a[i]].end(),r) - lower_bound(e[a[i]].begin(),e[a[i]].end(),l);
            if (tmp > cntt || (tmp == cntt && a[i] < temp))
            {
                temp = a[i];
                cntt = tmp;
            }
        }
        return temp;
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        block = sqrt(n);
        for (ll i = 1; i <= n; i++)
        {
            scanf("%lld",&a[i]);
            b[i] = a[i];
            pos[i] = (i - 1) / block + 1;
        }
        cnt = (n - 1) / block + 1;
        for (ll i = 1; i <= cnt; i++)
        {
            L[i] = R[i - 1] + 1;
            R[i] = min(i * block,n);
        }
        sort(b + 1,b + 1 + n);
        cntt = unique(b + 1,b + 1 + n) - b - 1;
        for (ll i = 1; i <= n; i++)
            a[i] = lower_bound(b + 1,b + 1 + cntt,a[i]) - b;
        for (ll i = 1; i <= n; i++)
            e[a[i]].push_back(i);
        for (ll i = 1; i <= n; i++)
            sort(e[i].begin(),e[i].end());
        for (ll i = 1; i <= cnt; i++)
            pre(i);
        for (ll i = 1; i <= m; i++)
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            l = (l + lastans - 1) % n + 1;
            r = (r + lastans - 1) % n + 1;
            if (l > r)
                swap(l,r);
            printf("%lld
    ",lastans = b[query(l,r)]);
        }
    
        return 0;
    }

     

  • 相关阅读:
    模仿Linux内核kfifo实现的循环缓存
    FFmpeg + SoundTouch实现音频的变调变速
    C++标准库实现WAV文件读写
    PHP写的一个轻量级的DI容器类(转)
    android App抓包工具的应用(转)
    Dell 服务器阵列扩容【经验分享(转)】
    hexo静态博客的安装及应用实践记录
    centos 6.5 升级php到5.6.17版本
    前端框架记录
    Virtual DOM 虚拟DOM的理解(转)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8563704.html
Copyright © 2011-2022 走看看