zoukankan      html  css  js  c++  java
  • bzoj4865: [Ynoi2017]由乃运椰子

    在线询问区间众数,传统的分块(记录块间众数和每个权值的出现次数)做法被卡空间(分块用的空间是O(块数*(块数+权值种类数))),因此考虑去掉出现次数较小的数,只用分块维护出现次数较大的数。设K为分界线,用原来的分块维护原序列中出现次数>K的数组成的部分,而出现次数<=K的数,可以通过记录一个数前面第1~K个相同的数的位置,用线段树维护,线段树查询时利用单调性单次询问可以做到$O(k+logn)$,不会成为瓶颈。

    当K取$O(n^{1/4})$时,时间复杂度仍是$O(qsqrt{n})$,空间复杂度为$O(n^{5/4})$

    #include<bits/stdc++.h>
    char buf[65555],*ptr=buf+65536;
    int g(){
        if(ptr-buf==65536)fread(buf,1,65536,stdin)[buf]=0,ptr=buf;
        return *ptr++;
    }
    int __(){
        int x=0,c=g();
        while(c<48)c=g();
        while(c>47)x=x*10+c-48,c=g();
        return x;
    }
    int _(){
        if(ptr-buf>65500)return __();
        int x=0,c=*ptr++;
        while(c<48)c=*ptr++;
        while(c>47)x=x*10+c-48,c=*ptr++;
        return x;
    }
    typedef unsigned short u16;
    int n,m;
    int v0[60007],vs[60007],B,v1[60007],vp1=0;
    u16 bc[365][6677],ws[60007],t[60007],rid[60007],bb[365][365],pv[60007],pw[60007];
    int ls[405],rs[405];
    u16 tr[131111][7];
    int max(int a,int b){return a>b?a:b;}
    int get(int l,int r){
        int p=0;
        for(int a=l+65535,b=r+65537;b-a!=1&&p<7;a>>=1,b>>=1){
            if(~a&1)while(p<7&&tr[a^1][p]>=l)++p;
            if(b&1)while(p<7&&tr[b^1][p]>=l)++p;
        }
        return p+1;
    }
    int main(){
        n=_();m=_();
        for(int i=1;i<=n;++i)vs[i]=v0[i]=_();
        std::sort(vs+1,vs+n+1);
        for(int i=1;i<=n;++i)v0[i]=std::lower_bound(vs+1,vs+n+1,v0[i])-vs;
        for(int i=1;i<=n;++i){
            int x=v0[i];
            pv[i]=pw[x];
            pw[x]=i;
            for(int j=0,z=pv[i];j<7;++j)tr[i+65536][j]=z,z=pv[z];
        }
        for(int i=65535;i;--i){
            int a=i<<1,b=a^1;
            for(int j=0;j<7;++j)tr[i][j]=max(tr[a][j],tr[b][j]);
        }
        for(int i=1;i<=n;++i)++t[v0[i]];
        int idp=0;
        for(int i=1;i<=n;++i)if(t[i]>8)rid[i]=++idp;
        
        for(int i=1;i<=n;++i)if(rid[v0[i]]){
            v1[++vp1]=rid[v0[i]];
            v0[i]=vp1;
        }else v0[i]=v0[i-1];
        for(int i=1;i<=n;++i)t[i]=0;
        n=vp1;
        for(B=1;n/B>362;++B);
        for(int l=1,r=B,c=1;l<=n;l+=B,r+=B,++c){
            if(r>n)r=n;
            ls[c]=l;rs[c]=r;
            for(int i=ls[c];i<=rs[c];++i)ws[i]=c;
            for(int b=c;b;--b){
                bb[c][b]=bb[c][b+1];
                for(int i=ls[b];i<=rs[b];++i)if(v1[i]){
                    int x=++bc[c][v1[i]];
                    if(x>bc[c][bb[c][b]])bb[c][b]=v1[i];
                }
            }
        }
        int la=0;
        while(m--){
            int L=_()^la,R=_()^la;
            int a0=get(L,R);
            L=v0[L-1]+1;R=v0[R];
            int l=ws[L],r=ws[R];
            if(a0<8)la=a0;
            else if(r-l<=1){
                la=a0;
                for(int i=L;i<=R;++i){
                    int x=v1[i];
                    if(x&&++t[x]>la)la=t[x];
                }
                for(int i=L;i<=R;++i)--t[v1[i]];
            }else{
                --r,++l;
                int mx=bb[r][l];
                u16*s1=bc[r],*s2=bc[l-1];
                for(int i=rs[l-1];i>=L;--i){
                    int x=v1[i];
                    int t1=++t[x]+s1[x]-s2[x];
                    if(t1>t[mx]+s1[mx]-s2[mx])mx=x;
                }
                for(int i=ls[r+1];i<=R;++i){
                    int x=v1[i];
                    int t1=++t[x]+s1[x]-s2[x];
                    if(t1>t[mx]+s1[mx]-s2[mx])mx=x;
                }
                la=max(a0,t[mx]+bc[r][mx]-bc[l-1][mx]);
                for(int i=rs[l-1];i>=L;--i)--t[v1[i]];
                for(int i=ls[r+1];i<=R;++i)--t[v1[i]];
            }
            printf("-%d
    ",la);
        }
        return 0;
    }
  • 相关阅读:
    Java IO流 简介
    Centos8安装java部署环境
    RedisTemplate
    手把手教windows上安装linux虚拟机及环境配置
    使用Swagger2构建 RESTful API文档
    VMware 安装 Centos 7 虚拟机配置网络
    别再写满屏的 try catch 了
    isEmpty 和 isBlank 的用法区别
    SpringBoot 中必须掌握的45个注解
    数组的栈方法
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7416292.html
Copyright © 2011-2022 走看看