zoukankan      html  css  js  c++  java
  • [题解] LuoguP4168 [Violet]蒲公英

    这个题原来是黑题的说

    传送门

    来写点清(fei)新(chang)一(du)点(liu)的分块题吧...

    一句话题意:求区间众数,强制在线。

    好像还有在线莫队的做法......不会 Orz

    众数这玩意儿不怎么好合并,所以考虑暴力分块。

    设每块的大小为(t),我们维护三个东西

    • (cc[i][j])表示前(i)个块中,元素(j)出现了多少次(当然要离散化辣~~)
    • (ansv[i][j])(i)个块到第(j)个块内的众数
    • (ansc[i][j])(i)个块到第(j)个块内众数的出现次数

    考虑怎么算这三个东西,(cc)的话(O(n/t))的扫一遍所有的块,然后每次(O(t))遍历块中元素就好了,复杂度为(O(n/t^2))

    (ansv[i][j])(ansc[i][j]),枚举(i),然后在从左到右枚举(j)的时候遍历第(j)个块内的所有元素,随便开个桶算一下,复杂度(O((n/t)^2 imes t)=O(n^2/t))

    于是预处理的复杂度就是(O(n^2/t))

    考虑查询区间([l,r])的答案,如果(l,r)在同一块中直接暴力就好了。

    如果不在假设第(bl)块到第(br)块被区间([l,r])完全包含,刚开始的答案就是(ansc[bl][br]),然后枚举边角块的元素,维护个桶,更新答案即可。

    因为(n,m)同阶,这里就用(n)好了,回答的总复杂度是(O(2tn))

    这样总复杂度就是(n^2/t+2tn),考虑(t)的取值。

    (f(x)=n^2/x+2nx),求导得到(f'(x)=2n-n^2x^{-2}),当(f'(x)=0)时,解得(x=(n/2)^{1/2})

    (t=(n/2)^{1/2})的时候就能得到一个较优的复杂度,大概是(O(n^{frac{3}{2}}))

    (Code)

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;++i)
    #define per(i,a,n) for (int i=n-1;i>=a;--i)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    
    const int N=4e4+10;
    struct node {
        int v,x,id;
    }a[N];
    int n,m,tn,tb,tot;
    
    int bel[N],cc[300][N],ansv[300][300],ansc[300][300];
    int lb[300],rb[300];
    void init() {
        tn=(int)(pow(n/2.0,0.5)+0.5);
        rep(i,1,n+1) {
            bel[i]=(i-1)/tn+1,tb=bel[i];
            lb[bel[i]]=lb[bel[i]]==0?i:lb[bel[i]];
            rb[bel[i]]=i;
        }
        rep(i,1,tb+1) rep(j,lb[i],rb[i]+1) cc[i][a[j].x]++;
        rep(i,1,tb+1) rep(j,1,tot+1) cc[i][j]+=cc[i-1][j];
        rep(i,1,tb+1) {
            static int cnt[N];
            int mxc=0,mxv=0;
            rep(j,i,tb+1) {
                rep(k,lb[j],rb[j]+1) {
                    ++cnt[a[k].x];
                    if(cnt[a[k].x]>mxc||(cnt[a[k].x]==mxc&&a[k].v<mxv))
                        mxv=a[k].v,mxc=cnt[a[k].x];
                }
                ansv[i][j]=mxv,ansc[i][j]=mxc;
            }
            rep(j,i,tb+1) rep(k,lb[j],rb[j]+1) --cnt[a[k].x];
        }
    }
    
    #define getcc(l,r,k) (cc[r][k]-cc[l-1][k])
    
    int query(int l,int r) {
        static int cnt[N];
        int bbl=bel[l],bbr=bel[r];
        if(bbl==bbr) {
            int ans1=0,ans2=0;
            rep(i,l,r+1) {
                ++cnt[a[i].x];
                if(cnt[a[i].x]>ans2||(cnt[a[i].x]==ans2&&a[i].v<ans1))
                    ans1=a[i].v,ans2=cnt[a[i].x];
            }
            rep(i,l,r+1) --cnt[a[i].x];
            return ans1;
        }
        int l0=1,r0=0,l1=1,r1=0;
        if(lb[bbl]!=l) l0=l,r0=rb[bbl],++bbl;
        if(rb[bbr]!=r) l1=lb[bbr],r1=r,--bbr;
        int ans1=ansv[bbl][bbr],ans2=ansc[bbl][bbr];
        rep(i,l0,r0+1) {
            ++cnt[a[i].x];
            int tmpc=cnt[a[i].x]+getcc(bbl,bbr,a[i].x);
            if(tmpc>ans2||(tmpc==ans2&&a[i].v<ans1))
                ans1=a[i].v,ans2=tmpc;
        }
        rep(i,l1,r1+1) {
            ++cnt[a[i].x];
            int tmpc=cnt[a[i].x]+getcc(bbl,bbr,a[i].x);
            if(tmpc>ans2||(tmpc==ans2&&a[i].v<ans1))
                ans1=a[i].v,ans2=tmpc;
        }
        rep(i,l0,r0+1) --cnt[a[i].x];
        rep(i,l1,r1+1) --cnt[a[i].x];
        return ans1;
    }
    
    int main() {
    #ifdef LOCAL
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    #endif
        scanf("%d%d",&n,&m);
        rep(i,1,n+1) {
            scanf("%d",&a[i].v);
            a[i].id=i;
        }
        sort(a+1,a+n+1,[](node a,node b) {
            return a.v<b.v;
        });
        rep(i,1,n+1) a[i].x=a[i].v==a[i-1].v?a[i-1].x:++tot;
        sort(a+1,a+n+1,[](node a,node b) {return a.id<b.id;});
        init();
        int lstans=0; while(m--) {
            int l,r; scanf("%d%d",&l,&r);
            l=(l+lstans-1)%n+1,r=(r+lstans-1)%n+1;
            if(l>r) swap(l,r);
            printf("%d
    ",lstans=query(l,r));
        }
        return 0;
    }
    

    感觉跑的还挺快的qwq

  • 相关阅读:
    os.remove some jpgs
    shutil.rmtree, os.path, delete sub-folders, format
    How to create folder
    valgrind
    gstream
    TP TN FP FN
    tensor flow
    接口中静态方法和默认方法
    JAVA基础09
    JAVA基础08
  • 原文地址:https://www.cnblogs.com/wxq1229/p/12389635.html
Copyright © 2011-2022 走看看