P5048 题解

吐槽:感觉本题最多紫。


考虑分块,设块长为 (S)

离散化序列之后,设 (f_{i,j}) 表示第 (i,i+1,dots,j) 块的众数出现次数,可以在 (O((dfrac{n}{S})^2 imes S))=O(dfrac{n^2}{S})) 时间内预处理出来。

查询的时候先把整段的答案算出来,考虑零碎部分怎么算。

设目前算出的众数的出现数量为 (ans)

此时传统的做法是值域分块查询这个数在一个区间中出现次数,但是我们要算的比这个弱很多,只要判断这个数在这个区间内出现次数为 (ans+1) 即可。

那我们只要对每个值开个 vector,按顺序维护这个值对应的所有下标,然后判断左边零碎时我们只要判断在右边 (ans) 个是否在 ([l,r]) 中,判断右边零碎时我们只要判断在左边 (ans) 个是否在 ([l,r]) 中即可。

时间复杂度 (O(dfrac{n^2}{S}+mS)),空间复杂度 (O(n))

(S=dfrac{n}{sqrt m}) 可得复杂度为 (O(nsqrt m))

一点也不卡常,习惯性开个论文鸽快读就过了。

Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct IO_Tp {
    const static int _I_Buffer_Size = 2 << 23;
    char _I_Buffer[_I_Buffer_Size], *_I_pos = _I_Buffer;

    const static int _O_Buffer_Size = 2 << 23;
    char _O_Buffer[_O_Buffer_Size], *_O_pos = _O_Buffer;

    IO_Tp() { fread(_I_Buffer, 1, _I_Buffer_Size, stdin); }
    ~IO_Tp() { fwrite(_O_Buffer, 1, _O_pos - _O_Buffer, stdout); }

    IO_Tp &operator>>(int &res) {
    	int f=1;
        while (!isdigit(*_I_pos)&&(*_I_pos)!='-') ++_I_pos;
        if(*_I_pos=='-')f=-1,++_I_pos;
        res = *_I_pos++ - '0';
        while (isdigit(*_I_pos)) res = res * 10 + (*_I_pos++ - '0');
        res*=f;
        return *this;
    }

    IO_Tp &operator<<(int n) {
    	if(n<0)*_O_pos++='-',n=-n;
        static char _buf[10];
        char *_pos = _buf;
        do
            *_pos++ = '0' + n % 10;
        while (n /= 10);
        while (_pos != _buf) *_O_pos++ = *--_pos;
        return *this;
    }

    IO_Tp &operator<<(char ch) {
        *_O_pos++ = ch;
        return *this;
    }
} IO;
const int N=500005,S=715;
int n,m,bl,num,a[N],b[N],L[S],R[S],f[S][S],tot[N],pl[N];
vector<int>v[N];
int query(int l,int r){
	int ret=0;
	if(b[l]==b[r]){
		for(int i=l;i<=r;i++)ret=max(ret,++tot[a[i]]);
		for(int i=l;i<=r;i++)tot[a[i]]=0;
		return ret;
	}
	ret=f[b[l]+1][b[r]-1];
	for(int i=l;i<=R[b[l]];i++)while(pl[i]+ret<v[a[i]].size()&&v[a[i]][pl[i]+ret]<=r)ret++;
	for(int i=L[b[r]];i<=r;i++)while(pl[i]-ret>=0&&v[a[i]][pl[i]-ret]>=l)ret++;
	return ret;
} 
int main(){
	IO>>n>>m;
	for(int i=1;i<=n;i++)IO>>a[i],b[i]=a[i];
	sort(b+1,b+n+1);
	num=unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b,pl[i]=v[a[i]].size(),v[a[i]].push_back(i);
	bl=sqrt(n);
	for(int i=1;i<=n;i++)b[i]=(i-1)/bl+1;
	num=b[n];
	for(int i=1;i<=num;i++)L[i]=R[i-1]+1,R[i]=i*bl;
	R[num]=n;
	for(int i=1;i<=num;i++){
		memset(tot,0,sizeof(tot));
		for(int j=i;j<=num;j++){
			f[i][j]=f[i][j-1];
			for(int k=L[j];k<=R[j];k++)f[i][j]=max(f[i][j],++tot[a[k]]);
		}
	}
	memset(tot,0,sizeof(tot));
	for(int lastans=0;m--;){
		int l,r;
		IO>>l>>r;
		l^=lastans,r^=lastans;
		IO<<(lastans=query(l,r))<<'
';
	}
	return 0;
}
原文地址:https://www.cnblogs.com/happydef/p/13927132.html