• 算法初探


    正文

    我与你无冤无仇,为何拿Ynoi做例题

    分块,顾名思义就是分块,这是接触根号复杂度的开端

    将要进行维护的东西分成 (sqrt{n})

    en,然后分别进行维护

    直接拿例题开讲

    P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III

    典型的区间求众数题,不过这道题要求我们输出众数出现的个数而不是众数它本身

    因为众数不具有区间可加性,所以线段树维护啥的就变得困难

    考虑分块

    我们将数列分成 (sqrt{n}) 段,预处理出第 (i)(j) 段的众数,并将每个数出现的次数记录下来

    然后就开始进行查询

    • 如果 (l,r) 在同一块里,暴力统计

    • 如果不在同一块里,左右边界分别暴力统计

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    #define N 500001
    #define M 708
    #define R register int
    int n,m,v[N],ql,qr,st[N],discn,cnt[N],apr[M][M],ans,l[M],r[M],to[N],sz,szl[N],bfl,bfr;
    std::vector<int>aprp[N];
    inline void read(int &x){
    	x=0;
        int w=1,ch=getchar();
        while(!isdigit(ch)&&ch!='-') ch=getchar();
        if(ch=='-') w=-1,ch=getchar();
        while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
        x*=w;
    }
    inline void write(int x){
        if(x<0) x=-x,putchar('-');
        if(x>9) write(x/10);
    	putchar(x%10+'0');
    }
    inline int max(int a,int b) {return a>b?a:b;}
    signed main(){
    	read(n),read(m);
    	for(R i=1;i<=n;++i) read(v[i]),st[i]=v[i];
    	std::sort(st+1,st+n+1);
    	discn=std::unique(st+1,st+n+1)-st-1;
    	for(R i=1;i<=n;++i){
    		v[i]=std::lower_bound(st+1,st+discn+1,v[i])-st;
    		aprp[v[i]].push_back(i);
    		szl[i]=aprp[v[i]].size()-1;
    	}
    	sz=(n-1)/M+1;
    	for(R i=1;i<=sz;++i){
    		l[i]=r[i-1]+1;r[i]=i*M;
    		for(R o=l[i];o<=r[i]&&o<=n;++o) to[o]=i;
    	}
    	r[sz]=n;
    	for(R i=2;i<sz;++i){
    		for(R o=i;o<sz;++o){
    			int &rs=apr[i][o];
    			rs=apr[i][o-1];
    			for(R p=l[o];p<=r[o];++p)
    				rs=max(rs,++cnt[v[p]]);
    		}
    		memset(cnt,0,sizeof(cnt));
    	}
    	while(m--){
    		read(ql),read(qr);
    		ql^=ans,qr^=ans;ans=0;
    		bfl=to[ql],bfr=to[qr];
    		if(bfl==bfr){
    			for(R i=ql;i<=qr;++i) ans=max(ans,++cnt[v[i]]);
    			for(R i=ql;i<=qr;++i) cnt[v[i]]=0;
    		}
    		else{
    			ans=apr[bfl+1][bfr-1];
    			for(R i=ql;i<=r[bfl];++i)
    				while(szl[i]+ans<aprp[v[i]].size()&&aprp[v[i]][szl[i]+ans]<=qr) ans++;
    			for(R i=qr;i>=l[bfr];--i)
    				while(szl[i]-ans>=0&&aprp[v[i]][szl[i]-ans]>=ql) ans++;
    		}
    		write(ans);putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    【游戏开发】Excel表格批量转换成CSV的小工具
    iOS
    iOS
    Xcode
    iOS
    iOS
    iOS
    iOS
    iOS
    iOS
  • 原文地址:https://www.cnblogs.com/zythonc/p/13732609.html
Copyright © 2020-2023  润新知