• Bzoj4241: 历史研究——回滚莫队


    题面

      Bzoj

    解析

      今天Doggu讲了根号类算法,这道题使用的就是其中之一的回滚莫队。

      这道题显然支持离线操作,询问区间,立即联想到莫队,对于区间扩大的信息更新是很容易的,但要区间缩小,信息的更新就很难了,于是就有一个叫做回滚莫队的东西。思路大体与莫队一致,只是对于块内询问每一次都暴力解决, 对于跨越块的询问,固定左指针在块的右端点+1的位置,先延伸右指针, 记录此时的答案now, 再延伸左指针,统计答案,然后左指针撤回到所在块的右端点+1的位置,同时将之前记录的答案now赋给现在的答案,这个操作叫做回滚。

      还有要注意常数优化,我之前的写法写挂了无数次。

     代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 100005;
    
    template<class T>
    inline void read(T &re)
    {
        re=0;
        T sign=1;
        char tmp;
        while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;
        re=tmp-'0';
        while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=(re<<3)+(re<<1)+(tmp-'0');
        re*=sign;
    }
    
    int n, Q, siz, pos[maxn], a[maxn], b[maxn], tot, t[maxn];
    ll ans[maxn];
    
    struct question{
        int l, r, num;
    }q[maxn];
    
    inline bool cmp(question x, question y)
    {
        if(pos[x.l] == pos[y.l])
            return x.r < y.r;
        return pos[x.l] < pos[y.l];
    }
    
    inline void work()
    {
        register int las = 0, L, R;
        register ll res = 0;
        for(register int i = 1; i <= Q; ++i)
        {
            if(pos[q[i].l] != las)
            {
                for(register int j = 1; j <= tot; ++j)
                    t[j] = 0;
                res = 0;
                L = min(siz * pos[q[i].l], n) + 1;
                R = L - 1;
            }
            if(pos[q[i].l] == pos[q[i].r])
            {
                for(register int j = q[i].l; j <= q[i].r; ++j)
                {
                    t[a[j]] ++;
                    res = max(res, 1LL * b[a[j]] * t[a[j]]);
                }
                for(int j = q[i].l; j <= q[i].r; ++j)
                    t[a[j]] --;
                ans[q[i].num] = res;
                res = 0;
                las = pos[q[i].l];
            }
            else
            {
                while(R < q[i].r)    
                {
                    R++;
                    t[a[R]]++;
                    res = max(res, 1LL * b[a[R]] * t[a[R]]);
                }
                ll now = res;
                register int ql = L;
                while(q[i].l < L)
                {
                    L --;
                    t[a[L]] ++;
                    res = max(res, 1LL * b[a[L]] * t[a[L]]);
                }
                ans[q[i].num] = res;
                while(L < ql)
                    t[a[L++]] --;
                res = now;
                las = pos[q[i].l];
            }
        }
    }
    
    int main()
    {
        read(n);read(Q);
        siz = (int)sqrt(n * 1.0 + 0.5);
        for(register int i = 1; i <= n; ++i)
            read(a[i]), b[i] = a[i];
        sort(b + 1, b + n + 1);
        tot = unique(b + 1, b + n + 1) - b - 1;
        for(register int i = 1; i <= n; ++i)
        {
            a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
            pos[i] = (i - 1) / siz + 1;
        }
        for(register int i = 1; i <= Q; ++i)
        {
            read(q[i].l);read(q[i].r);
            q[i].num = i;
        }
        sort(q + 1, q + Q + 1, cmp);
        work();
        for(int i = 1 ; i <= Q; ++i)
            printf("%lld
    ", ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    LNMP 部署
    zabbix3.2安装graphtree3.0.4
    升级java8---from centos
    mysql5.6-5.7性能调优
    samba server install
    centos7 zabbix3 install done
    实验四总结
    第五周学习小结
    个人的一些html、css笔记
    为什么wait,notify,notifyAll定义在Object中?
  • 原文地址:https://www.cnblogs.com/Joker-Yza/p/11234200.html
Copyright © 2020-2023  润新知