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
",Ans[i]);
70 }
原文地址:https://www.cnblogs.com/fzmh/p/5398290.html