bzoj4241 历史研究
莫队算法,只考虑对一个序列加入数字的话,重要度的维护是O(1)的,排完序后的询问,若左端点是在同一块中的话,右端点递增。因为右端点是递增的因此可以O(1)维护,而左端点的话,对于每个询问我们可以暴力插入,询问后还原,对于一次询问来说是O(sqrtn)的
,因此总复杂度O(nsqrtn)
1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 #define N 200010 5 using namespace std; 6 int n,m,i,a[N],b[N],c[N],tot,j,k,o; 7 long long ans,tmp,Ans[N],sum[N]; 8 int cur,lim; 9 map<int,int> id; 10 struct g{ 11 int l,r,id; 12 }q[N]; 13 bool cmp(g a,g b) 14 { 15 if (a.l/300==b.l/300) 16 return a.r<b.r; 17 return a.l/300<b.l/300; 18 } 19 int main() 20 { 21 scanf("%d%d",&n,&m); 22 for (i=1;i<=n;i++) 23 scanf("%d",&a[i]),b[i]=a[i]; 24 sort(a+1,a+1+n); 25 for (i=1;i<=n;i++) 26 { 27 if (a[i]!=a[i-1]) tot++; 28 id[a[i]]=tot; 29 } 30 for (i=1;i<=n;i++) 31 c[i]=id[b[i]]; 32 for (i=1;i<=m;i++) 33 { 34 scanf("%d%d",&q[i].l,&q[i].r); 35 q[i].id=i; 36 } 37 38 sort(q+1,q+1+m,cmp); 39 for (i=1;i<=m;i++) 40 { 41 for (j=i;j<=m;j++) 42 if (q[j].l/300!=q[i].l/300) break; 43 k=j-1;cur=(q[i].l/300+1)*300;lim=cur-1; 44 ans=0; 45 for (j=1;j<=tot;j++) 46 sum[j]=0; 47 for (j=i;j<=k;j++) 48 { 49 while (cur<=q[j].r) 50 { 51 sum[c[cur]]++; 52 ans=max(ans,sum[c[cur]]*b[cur]); 53 cur++; 54 } 55 tmp=ans; 56 for (o=q[j].l;o<=min(q[j].r,lim);o++) 57 { 58 sum[c[o]]++; 59 tmp=max(tmp,sum[c[o]]*b[o]); 60 } 61 Ans[q[j].id]=tmp; 62 for (o=q[j].l;o<=min(q[j].r,lim);o++) 63 sum[c[o]]--; 64 } 65 i=k; 66 } 67 68 for (i=1;i<=m;i++) 69 printf("%lld\n",Ans[i]); 70 }