其他分享
首页 > 其他分享> > 回滚莫队 刷题记录

回滚莫队 刷题记录

作者:互联网

BZOJ4241: 历史研究

给一个长为n的数组,q次查询,查询l~r区间内某个数的值乘以该数出现的次数的最大值。

明显添加比较容易删除比较难,所以回滚莫队

先离散化数,然后在莫队的时候维护桶。

所谓回滚莫队就是lefl每次都到块的最右边这样就不会有删除操作了。

 1 #include <bits/stdc++.h>
 2 #define nmax 100010
 3 #define f1n for(int i=1; i<=n; i++)
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 int n, q, nb, cb;
 8 ll pa[nmax], cnt[nmax], fi[nmax];
 9 int c[nmax];
10 int pos[nmax];
11 struct ques{
12     int l, r, pl, id;
13     bool operator < (const ques myc) const {
14         return (myc.pl==pl) ? (myc.r>r) : (myc.pl>pl) ;
15     } //----------
16 }qe[nmax];
17 struct mylsh{
18     ll x; 
19     int id;
20     bool operator < (const mylsh myc) const { return myc.x > x; }
21 }lsh[nmax];
22 
23 void build(){
24     scanf("%d%d", &n, &q);
25     nb = (int)sqrt(n);
26     f1n {
27         scanf("%lld", &lsh[i].x);
28         lsh[i].id = i;
29     }
30     sort(lsh+1, lsh+1+n);
31     int j=0;  
32     lsh[0].x = lsh[1].x+1; 
33     f1n{
34         if(lsh[i].x != lsh[i-1].x) j++;
35         c[ lsh[i].id ] = j;
36         fi[j] = lsh[i].x;
37     }
38     f1n pos[i] = (i-1)/nb+1; //--------
39     for (int i=1; i<=q; i++) {
40         scanf("%d%d", &qe[i].l, &qe[i].r);
41         qe[i].id = i;
42         qe[i].pl = pos[ qe[i].l ];
43     }
44     sort(qe+1, qe+1+q);
45 }
46 
47 inline void upd(int p, ll& ta){
48     cnt[ c[p] ]++;
49     ta = max( ta, cnt[ c[p] ]*fi[ c[p] ] );
50 }
51 
52 inline void init(){  memset(cnt,0,sizeof(cnt)); }
53 
54 inline ll myf(int l, int r){
55     ll ans=0;
56     for (int i=l; i<=r; i++) {
57         cnt[ c[i] ]++;
58         ans = max(ans, cnt[ c[i] ] * fi[ c[i] ] );
59     }
60     for (int i=l; i<=r; i++) cnt[ c[i] ]--;
61     return ans;
62 }
63 
64 int main(){
65     //freopen("owo.in","r",stdin);
66     build();
67     int tr, tmp;
68     ll ta;
69     qe[0].pl=-1;
70     for (int i=1; i<=q; i++) {
71         if( qe[i].pl != qe[i-1].pl ) {
72             init();
73             tmp = qe[i].pl*nb;
74             tr = tmp;
75             ta = 0;
76         }
77         if( pos[ qe[i].r ] == qe[i].pl ) pa[ qe[i].id ] = myf(qe[i].l, qe[i].r);
78         else{
79             while(qe[i].r>tr) { tr++; upd(tr, ta); }
80             ll jl = ta;
81             for (int k = tmp; k>=qe[i].l; k--) upd(k, ta); 
82             pa[ qe[i].id ] = ta;
83             for (int k = tmp; k>=qe[i].l; k--) cnt[ c[k] ]--; //撤销影响
84             ta = jl;
85         }
86     }
87     for (int i=1; i<=q; i++) printf("%lld\n", pa[i]);
88     return 0;
89 }
( *^-^)ρ(*╯^╰)

 

标签:回滚,f1n,int,lsh,qe,刷题,莫队,ta
来源: https://www.cnblogs.com/jiecaoer/p/11980402.html