BZOJ 4241 历史研究(分块)
题意
题解
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int N=100100; 8 int n,m,Block,block[N],a[N],b[N],cnt[400][N],top,stack[N],num[N]; 9 long long f[400][N]; 10 int main(){ 11 scanf("%d%d",&n,&m); 12 Block=sqrt(n); 13 for(int i=1;i<=n;i++){ 14 scanf("%d",&a[i]); 15 block[i]=(i-1)/Block+1; 16 b[i]=a[i]; 17 } 18 sort(b+1,b+1+n); 19 int tot=unique(b+1,b+1+n)-b-1; 20 for(int i=1;i<=n;i++){ 21 a[i]=lower_bound(b+1,b+1+tot,a[i])-b; 22 } 23 for(int i=1;i<=block[n];i++){ 24 long long ans=0; 25 for(int j=lower_bound(block+1,block+1+n,i)-block;j<=n;j++){ 26 cnt[i][a[j]]++; 27 ans=max(ans,(long long)cnt[i][a[j]]*b[a[j]]); 28 f[i][j]=ans; 29 } 30 } 31 for(int i=1;i<=m;i++){ 32 top=0; 33 int x,y; 34 scanf("%d%d",&x,&y); 35 long long ans=f[block[x]+1][y]; 36 int tmp=lower_bound(block+1,block+1+n,block[y])-block; 37 for(int j=tmp;j<=y;j++){ 38 num[a[j]]++; 39 stack[++top]=a[j]; 40 } 41 tmp=lower_bound(block+1,block+1+n,block[x]+1)-block; 42 for(int j=x;j<=tmp-1;j++){ 43 num[a[j]]++; 44 ans=max(ans,(long long)(cnt[block[x]+1][a[j]]-cnt[block[y]][a[j]]+num[a[j]])*b[a[j]]); 45 stack[++top]=a[j]; 46 } 47 printf("%lld\n",ans); 48 for(int j=1;j<=top;j++)num[stack[j]]=0; 49 } 50 return 0; 51 }