就是区间众数的做法啦。。一模一样。
分块这种东西真的很容易写错。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxn 100050 using namespace std; int n,q,x[maxn],hash[maxn],cnt=0,s[maxn],top=0,blo[maxn],tot=0,se[maxn],l,r; int num[2050][2050],len,ll[maxn]; vector <int> v[maxn]; int read() { int data=0;char ch; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void build() { for (int i=1;i<=n;i++) hash[++cnt]=x[i]; sort(hash+1,hash+cnt+1);cnt=unique(hash+1,hash+cnt+1)-hash-1; len=80;tot=1; for (int i=1;i<=n;i++) { x[i]=lower_bound(hash+1,hash+cnt+1,x[i])-hash; v[x[i]].push_back(i); blo[i]=tot; if ((i%len==0) || (i==n)) { se[tot]=i; tot++; } } tot--; for (int i=1;i<=tot;i++) { long long mx=0;int ret; memset(ll,0,sizeof(ll)); for (int j=se[i-1]+1;j<=n;j++) { ll[x[j]]++; if (mx<(long long)ll[x[j]]*hash[x[j]]) {mx=(long long)ll[x[j]]*hash[x[j]];ret=x[j];} if ((j%len==0) || (j==n)) num[i][blo[j]]=ret; } } } int ask(int x,int num) { int l=0,r=v[num].size()-1,ans=-1,mid; while (l<=r) { mid=(l+r)>>1; if (v[num][mid]<=x) {ans=mid;l=mid+1;} else r=mid-1; } return ans+1; } long long work(int l,int r) { top=0; if (blo[l]+1>=blo[r]) { for (int i=l;i<=r;i++) s[++top]=x[i]; } else { s[++top]=num[blo[l]+1][blo[r]-1]; for (int i=l;i<=se[blo[l]];i++) s[++top]=x[i]; for (int i=se[blo[r]-1]+1;i<=r;i++) s[++top]=x[i]; } long long ret=0; for (int i=1;i<=top;i++) ret=max(ret,(long long)(ask(r,s[i])-ask(l-1,s[i]))*hash[s[i]]); return ret; } int main() { n=read();q=read(); for (int i=1;i<=n;i++) x[i]=read(); build(); for (int i=1;i<=q;i++) { l=read();r=read(); printf("%lld\n",work(l,r)); } return 0; }