4241: 历史研究

回滚莫队 …
就是说对于这题来说,添加容易,但是删除困难,那么就不考虑删除,即把左右端点分别放在块的两边,中间的是可以直接处理出来,然后块中的暴力更新,完了以后再变更为更新前的状态即可.
复杂度 O(nn) O ( n n )
c++代码如下:

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ; i <= (y); ++ i )
#define repd(i,x,y) for(register int i = x ; i >= (y); -- i )
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
    char c;int sign = 1;x = 0;
    do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 1e5+50;
int n,m,id[N],num[N],belong[N]; ll mx,cnt,ans[N],a[N],w[N];
struct DATA { int l,r,id; }Q[N];

const bool cmp(DATA a,DATA b) { return belong[a.l] < belong[b.l] || belong[a.l] == belong[b.l] && belong[a.r] < belong[b.r]; }

int main()
{
    read(n); read(m);
    rep(i,1,n) read(a[i]),w[i] = a[i];
    rep(i,1,m) read(Q[i].l), read(Q[i].r), Q[i].id = i;

    int d = (int)sqrt(n);

    sort(w + 1,w + 1 + n);
    rep(i,1,n) id[i] = lower_bound(w+1,w+1+n,a[i]) - w;
    rep(i,1,n) belong[i] = (i / d) +1;

    sort(Q + 1, Q + 1 + m , cmp);

    int l,r;
    rep(j,1,m)
    {
        if(belong[Q[j].l] != belong[Q[j-1].l])
        {
            memset(num,0,sizeof num),cnt = 0;
            l = Q[j].l;
            while(belong[l+1] == belong[l])
                ++l;
            r = l - 1;
        }
        if(belong[Q[j].l] == belong[Q[j].r])
        {
            mx = 0;
            rep(i,Q[j].l,Q[j].r)
            {
                ++num[id[i]];
                mx = max(num[id[i]] * a[i],mx);
            }
            rep(i,Q[j].l,Q[j].r)
                --num[id[i]];
            ans[Q[j].id] = mx;
            continue;
        }

        while(belong[r] != belong[Q[j].r])
        {
            ++r;
            ++num[id[r]];
            cnt = max(cnt,num[id[r]] * a[r]);
        }

        mx = cnt;

        rep(i,Q[j].l,l-1)
        {
            ++num[id[i]];
            mx = max(num[id[i]] * a[i],mx);
        }

        rep(i,r+1,Q[j].r)
        {
            ++num[id[i]];
            mx = max(num[id[i]] * a[i],mx);
        }
        rep(i,r+1,Q[j].r) --num[id[i]];
        rep(i,Q[j].l,l-1) --num[id[i]];
        ans[Q[j].id] = mx;
    }

    rep(i,1,m) printf("%lld\n",ans[i]) ;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值