zoukankan      html  css  js  c++  java
  • 【题解】洛谷P5048 Yuno loves sqrt technology III

    洛谷P5048 Yuno loves sqrt technology III

    题意

    给你一个长为 (n)的序列 (a)(m) 次询问,每次查询一个区间的众数的出现次数,强制在线。

    (1leq n,m leq 5 imes 10^5,0leq a_ileq 10^9)

    题解

    分块,设块长为(S),先预处理第(i)块到第(j)块的众数的出现次数(f[i][j]),对于值域于中的每一个值,用vector按顺序记录(a)中出现该值的下标,同时记录(a)中每个元素在其对应vector中的下标。对于每一次询问(l,r),假设其包含的连续完整块的答案为(ans),由于非完整块中的元素最多(2S)个,故最多使答案增加(2S),我们依次检查这些元素能否是答案增大。对于左边的非完整块的元素(a_i),若其对应vector为(g),其在(g)中的下标为(p),如果(g[p+ans])存在且(g[p+ans]leq r),说明(a_i)([l,r])中的出现次数不会比(ans)更差,故可直接++(ans);对于右边的元素同理。注意每个检查只是判定了能否使(ans)变为(ans+1),而某个位置上的值可能使答案不止增大1,故需对每个位置需用while循环来进行检查。

    预处理部分时间复杂度(O((frac{n}{S})^2 imes S)=O(frac{n^2}{S})),询问部分复杂度(O(mS)),故总复杂度(O(frac{n^2}{S}+mS)),取(S=frac{n}{sqrt m})可得总复杂度(O(nsqrt m)),直接取(S=sqrt n),复杂度(O((n+m)sqrt n))也可通过。

    #include <bits/stdc++.h>
    #define pb(x) emplace_back(x)
    using namespace std;
    const int N=600100,M=1000;
    int id[N],f[M][M],n,m,b[N],c[N],nm,d[N],a[N],bs;
    vector<int> g[N];
    int ck1(int ans,int x){
    	int k=a[x],na=g[k].size(),p=d[x];
    	if(p+ans<na)return g[k][p+ans];
    	else return n+1;
    }
    int ck2(int ans,int x){
    	int k=a[x],p=d[x];
    	if(p-ans>=0)return g[k][p-ans];
    	else return -1;
    }
    void f1(){
    	scanf("%d%d",&n,&m);
    	bs=sqrt(n)+1;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		b[i]=a[i];
    		id[i]=(i-1)/bs+1;
    	}
    	nm=(n-1)/bs+1;
    	sort(b+1,b+1+n);
    	int np=unique(b+1,b+1+n)-b-1;
    	for(int i=1;i<=n;i++){
    		a[i]=lower_bound(b+1,b+1+np,a[i])-b;
    		g[a[i]].pb(i);d[i]=g[a[i]].size()-1;
    		assert(g[a[i]][d[i]]==i);
    	}
    	for(int i=1;i<=nm;i++){
    		int na=0;
    		for(int j=1;j<=np;j++){c[j]=0;}
    		for(int j=i;j<=nm;j++){
    			int l=(j-1)*bs+1,r=min(l+bs-1,n);
    			for(int k=l;k<=r;k++){
    				c[a[k]]++;
    				na=max(na,c[a[k]]);
    			}	
    			f[i][j]=na;
    		}
    		
    	}
    	int lstans=0;
    	while(m--){
    		int x,y;scanf("%d%d",&x,&y);
    		x^=lstans;y^=lstans;
    		int na=id[x],nb=id[y];
    		int ans=0;
    		if(na+1<=nb-1){ans=f[na+1][nb-1];}
    		for(int i=min(y,na*bs);i>=x;i--){
    			while(ck1(ans,i)<=y){
    				++ans;
    			}
    		}
    		for(int i=max(x,(nb-1)*bs+1);i<=y;i++){
    			while(ck2(ans,i)>=x){
    				++ans; 
    			}
    		}
    		lstans=ans;
    		printf("%d
    ",ans);
    	}
    }
    int main(){
    	f1();
    	return 0;
    }
    
    /*
    10 0
    2 3 5 1 5 5 4 4 3 5 
    
    
    4 1
    2 3 3 3
    2 4
    */
    
  • 相关阅读:
    通过 WakaTime 统计你写代码的时长
    CCF 202012-3 带配额的文件系统
    1
    prometheus 获取cpu利用率
    springboot使用@data注解,减少不必要代码-lombok插件
    django官方教程部署simpleui时候发现加载不到静态文件解决办法
    echarts关系图研究01
    SpringBoot代码方式禁用Druid Monitor
    virtualbox给已有磁盘扩展容量
    centos7 ssh免密登录配置
  • 原文地址:https://www.cnblogs.com/bobh/p/15026514.html
Copyright © 2011-2022 走看看