分块大法好。。
这题就是个带权的区间众数。。。离散化一下就是普通的区间众数了。
分成根号n块,预处理mx[i][j]表示第i块~第j块 这段区间里的众数,pr[i][j]表示前i块里,数字j出现了多少次。
所以每个询问的答案,要么是整块里的众数,要么是两侧零散的数。
整块里面每个数出现的次数就是pr[],两侧的出现次数就直接暴力累加。
分块果然好写= =
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=100233; 8 struct zs{ 9 int v,pos; 10 }a[maxn]; 11 ll b[maxn],cnt; 12 int l[333],r[333],id[maxn]; 13 int mx[333][333],pr[333][maxn]; 14 int num[maxn],mp[maxn]; 15 int i,j,k,n,m,kuai,x,y; 16 17 int ra;char rx; 18 inline int read(){ 19 rx=getchar(),ra=0; 20 while(rx<'0'||rx>'9')rx=getchar(); 21 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 22 } 23 bool cmp(zs a,zs b){return a.v==b.v?a.pos<b.pos:a.v<b.v;} 24 inline ll query(int x,int y){ 25 register int i;; 26 int idl=(x+kuai-1)/kuai,idr=(y+kuai-1)/kuai, ans=mx[idl+1][idr-1]; 27 if(idl==idr){ 28 for(i=x;i<=y;i++) 29 ++num[mp[i]],ans=b[ans]*num[ans]<b[mp[i]]*num[mp[i]]?mp[i]:ans; 30 ll sum=b[ans]*num[ans]; 31 for(i=x;i<=y;i++)num[mp[i]]=0; 32 return sum; 33 } 34 for(i=x;i<=r[idl];i++)++num[mp[i]]; 35 for(i=l[idr];i<=y;i++)++num[mp[i]]; 36 ll sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] );//printf(" sum:%lld %d %d %d ",sum,idl,idr,pr[idr-1][ans]-pr[idl][ans]+num[ans]); 37 for(i=x;i<=r[idl];num[mp[i]]=0,i++)if(num[mp[i]]) 38 if( b[mp[i]]*( pr[idr-1][mp[i]]-pr[idl][mp[i]]+num[mp[i]] ) > sum )ans=mp[i],sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] ); 39 for(i=l[idr];i<=y;num[mp[i]]=0,i++)if(num[mp[i]]) 40 if( b[mp[i]]*( pr[idr-1][mp[i]]-pr[idl][mp[i]]+num[mp[i]] ) > sum )ans=mp[i],sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] ); 41 return sum; 42 } 43 int main(){ 44 register int j,k; 45 n=read(),m=read(),kuai=min(n,323);//kuai=1; 46 for(i=1;i<=n;i++)a[i].v=mp[i]=read(),a[i].pos=i,id[i]=(i+kuai-1)/kuai; 47 for(i=1;i<=id[n];i++)l[i]=(i-1)*kuai+1,r[i]=min(n,i*kuai); 48 sort(a+1,a+1+n,cmp); 49 for(i=1;i<=n;mp[a[i].pos]=cnt,pr[id[a[i].pos]][cnt]++,i++) 50 if(a[i].v!=a[i-1].v)b[++cnt]=a[i].v; 51 52 for(i=1;i<=id[n];i++) 53 for(mx[i][i]=mp[l[i]],j=l[i]+1;j<=r[i];j++)if(b[mp[j]]*pr[i][mp[j]]>b[mx[i][i]]*pr[i][mx[i][i]])mx[i][i]=mp[j]; 54 for(i=2;i<=id[n];i++)for(j=1;j<=cnt;j++)pr[i][j]+=pr[i-1][j]; 55 for(i=1;i<id[n];i++){ 56 for(j=1;j<=cnt;j++)num[j]=pr[i][j]-pr[i-1][j]; 57 for(j=i+1;j<=id[n];/*printf("mx:%d %d %lld ",i,j,b[mx[i][j]]),*/j++) 58 for(mx[i][j]=mx[i][j-1],k=l[j];k<=r[j];k++) 59 num[mp[k]]++,mx[i][j]=b[mx[i][j]]*num[mx[i][j]]<b[mp[k]]*num[mp[k]]?mp[k]:mx[i][j]; 60 } 61 // printf(" %lld ",b[mx[1][id[n]]]); 62 memset(num,0,(cnt+1)<<2); 63 while(m--) 64 x=read(),y=read(), 65 printf("%lld ",query(x,y)); 66 return 0; 67 }