• bzoj 4241 历史研究


    一个长度为 $n$ 的序列,$q$ 次询问,给定 $[l,r]$,求最大的 $a imes (a 在 [l,r] 中出现次数)$

    $n,q leq 100000$

    sol:

    莫队,这道题加入一个数很容易,但不是很好删除一个数,所以我们魔改一下莫队的处理方式

    具体地:

    1.对于长度小于 $sqrt{n}$ 的询问,暴力

    2.每次对于一个块,处理左端点在这个块里的询问,对于每次询问,先把 $L$ 指针设为块的右端点,向右移动 $R$ 指针,求出这组询问答案没移动左端点时的结果,然后把 $L$ 往左移求出答案,这组询问求完之后把答案和 $cnt$ 数组恢复成没移动左端点时的结果

    这样是 $O(nsqrt{n})$ 的

    跑不过分块 QAQ

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    namespace IO{
        const int BS=(1<<23)+5; int Top=0;
        char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[30]; const char *fin=OT+BS-1;
        char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
        void flush(){fwrite(OT,1,OS-OT,stdout);}
        void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;}
        void write(LL x){
            if(!x){Putchar('0');return;} if(x<0) x=-x,Putchar('-');
            while(x) SS[++Top]=x%10,x/=10;
            while(Top) Putchar(SS[Top]+'0'),--Top;
        }
        int read(){
            int nm=0,fh=1; char cw=Getchar();
            for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
            for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
            return nm*fh;
        }
    } using namespace IO;
    const int maxn = 100100;
    int n, q, pos = 1, SZ;
    int a[maxn], v[maxn], cnt[maxn];
    int bl[maxn]; LL ans[maxn];
    struct Ques {
        int l, r, id;
        Ques(){}
        Ques(int _1, int _2, int _3) : l(_1), r(_2), id(_3){}
        inline bool operator < (const Ques &b) const {
            return bl[l] == bl[b.l] ? r < b.r : l < b.l;
        }
    }qs[maxn];
    int force_cnt[maxn];
    inline LL force(int l, int r) {
        LL ret = 0;
        rep(i, l, r) force_cnt[a[i]] = 0;
        rep(i, l, r) force_cnt[a[i]]++;
        rep(i, l, r) ret = max(ret, 1LL * force_cnt[a[i]] * v[a[i]]);
        return ret;
    }
    inline void modify(int &i, int pos) {
        int L = min(n, SZ * pos);
        int ql = L + 1, qr = L;
        LL tmp = 0;
        memset(cnt, 0, sizeof(cnt));
        for(; bl[qs[i].l] == pos; i++) {
            if(bl[qs[i].l] == bl[qs[i].r]) ans[qs[i].id] = force(qs[i].l, qs[i].r);
            else {
                while(qr < qs[i].r) {
                    qr++;
                    cnt[a[qr]]++;
                    tmp = max(tmp, 1LL * v[a[qr]] * cnt[a[qr]]);
                }
                LL tans = tmp;
                while(ql > qs[i].l) {
                    --ql;
                    cnt[a[ql]]++;
                    tmp = max(tmp, 1LL * v[a[ql]] * cnt[a[ql]]);
                }
                ans[qs[i].id] = tmp;
                while(ql < L + 1) {
                    cnt[a[ql]]--;
                    ql++;
                }
                tmp = tans;
            }
        }
    }
    int main() {
    //    freopen("2.in","r",stdin);
    //    freopen("buff.out","w",stdout);
        n = read(); q = read(); SZ = sqrt(n);
        rep(i, 1, n) v[i] = a[i] = read(), bl[i] = (i-1) / SZ + 1;
        sort(v + 1, v + n + 1);
        rep(i, 1, n) a[i] = lower_bound(v + 1, v + n + 1, a[i]) - v;
        rep(i, 1, q) {
            int l = read(), r = read();
            qs[i] = Ques(l, r, i);
        } sort(qs + 1, qs + q + 1);
        rep(i, 1, bl[n]) modify(pos, i);
        rep(i, 1, q) write(ans[i]), Putchar('
    ');
        flush();
    }
    View Code
  • 相关阅读:
    链表的常用操作
    android简易论坛的制作
    Bmob后端云的使用
    马哥第九周
    马哥第八周
    马哥第七周
    马哥第六周
    马哥第五周
    马哥第四周
    马哥第三周
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10648422.html
Copyright © 2020-2023  润新知