zoukankan      html  css  js  c++  java
  • 回滚莫队

    原理

    对于删除操作的贡献很难统计的修改 可以选择使用回滚莫队

    比如要求区间最值

    显然Max运算无法撤销 考虑如何快速处理删除贡献的操作

    处理不了 所以换种思路 不再删除贡献

    首先在莫队的sort时候 按照第一维bel,第二维r排序

    此时对于每个左端点在同一个块内的询问, 此时r单调递增

    所以对于r是没有删除操作的

    考虑在块内无序排列的l 其实每次从块的右端点往左开始跑就可以了

    每次暴力统计从块的右端点到l的贡献

    因为块长不超过(√N) 所以每次暴力处理复杂度也是根号的

    所以总复杂度(N√N)

    当左右端点都在同一个块内时直接暴力即可

    例题:

    A:历史研究

    求区间最值

    维护块右端点右边每个事件出现的次数 (cnt[x]) 最大值Mx

    维护块内每个事件出现次数 (tmp[x]) 最大值Max

    对于询问 先把右端点转移到合适的位置 维护cnt与Mx

    然后从块的右端点开始往左跑 每次维护tmp 与Max

    当前事件的贡献就是((cnt[x] + tmp[x]) * x)

    每次处理完将tmp清空就好了




    B:permu

    求区间最大连续段长度

    删除操作不好处理 一样考虑回滚

    在块的右端点右边维护 ld[x],l[x],rd[x],r[x] 分别表示x这个数向左最多多少长度是连续的, 最左边的数是多少,右边同理

    以及此时的答案

    在块内维护 tmpld[x],tmpl[x],tmprd[x],tmpr[x] 定义与块右边的相同

    然后转移就可以了 每次加入一个新数 用左右两边的数更新它,再用它更新左右两边的值

    tmp处理的时候有个细节是 如果此时tmpl[x-1]没有值, 需要用l[x-1]更新, r同理

    每次更新维护答案 得解

    复杂度 (N√N) 但是没有跑过(N√Nlog_N) 维护东西太多导致常数太大了
    (C++ NOI (N√NlogN)跑不过去,这个能跑

    (细节挺多但是一遍过了

    显示代码

    include<bits/stdc++.h>

    using namespace std;

    define rint register int

    const int maxn = 1e5 + 10;
    int tld[maxn],trd[maxn],tl[maxn],tr[maxn];
    int l[maxn],r[maxn],ld[maxn],rd[maxn];
    int stl[maxn],str[maxn];
    int ans[maxn];
    int a[maxn];
    int Mx,sqr,cur,top1,top2;

    struct node{
    int l,r,bel,id;
    friend bool operator <(const node &A,const node &B) {return A.bel == B.bel ? A.r < B.r : A.bel < B.bel;}
    }q[maxn];

    int main(){
    rint n,m; scanf("%d%d",&n,&m); sqr = sqrt(n);
    for(rint i = 1;i <= n;++i) scanf("%d",&a[i]);
    for(rint i = 1;i <= m;++i) scanf("%d%d",&q[i].l,&q[i].r),q[i].bel = (q[i].l - 1) / sqr + 1, q[i].id = i;
    sort(q+1,q+m+1);
    rint tail = 0;
    for(rint i = 1;i <= m;++i) {
    rint L = q[i].l,R = q[i].r;
    if(q[i].bel != q[i-1].bel) {
    memset(l,0,sizeof(l)); memset(ld,0,sizeof(ld));
    memset(r,0,sizeof(r)); memset(rd,0,sizeof(rd));
    tail = q[i].bel * sqr; Mx = 0;
    }
    if(R <= q[i].bel * sqr) {
    cur = 0;
    for(rint j = L;j <= R;++j) {
    tld[a[j]] = tld[a[j]-1] + 1;
    trd[a[j]] = trd[a[j]+1] + 1;
    tl[a[j]] = tld[a[j]-1] ? tl[a[j]-1] : a[j];
    tr[a[j]] = trd[a[j]+1] ? tr[a[j]+1] : a[j];
    if(tld[a[j]-1]) trd[tl[a[j]-1]] += trd[a[j]], tr[tl[a[j]-1]] = tr[a[j]];
    if(trd[a[j]+1]) tld[tr[a[j]+1]] += tld[a[j]], tl[tr[a[j]+1]] = tl[a[j]];
    cur = max(cur,tld[tr[a[j]]]);
    }
    for(rint j = L;j <= R;++j) tld[a[j]] = trd[a[j]] = tl[a[j]] = tr[a[j]] = 0;
    ans[q[i].id] = cur;
    continue;
    }
    while(tail < R) {
    ++tail;
    ld[a[tail]] = ld[a[tail]-1] + 1;
    rd[a[tail]] = rd[a[tail]+1] + 1;
    l[a[tail]] = ld[a[tail]-1] ? l[a[tail]-1] : a[tail];
    r[a[tail]] = rd[a[tail]+1] ? r[a[tail]+1] : a[tail];
    if(ld[a[tail]-1]) rd[l[a[tail]-1]] += rd[a[tail]], r[l[a[tail]-1]] = r[a[tail]];
    if(rd[a[tail]+1]) ld[r[a[tail]+1]] += ld[a[tail]], l[r[a[tail]+1]] = l[a[tail]];
    Mx = max(Mx,ld[r[a[tail]]]);
    }
    cur = Mx;
    for(rint j = L;j <= q[i].bel * sqr;++j) {
    tld[a[j]] = (tld[a[j]-1] ? tld[a[j]-1] : ld[a[j]-1]) + 1;
    trd[a[j]] = (trd[a[j]+1] ? trd[a[j]+1] : rd[a[j]+1]) + 1;
    tl[a[j]] = (tld[a[j]-1] ? tld[a[j]-1] : ld[a[j]-1]) ? (tl[a[j]-1] ? tl[a[j]-1] : l[a[j]-1]) : a[j];
    tr[a[j]] = (trd[a[j]+1] ? trd[a[j]+1] : rd[a[j]+1]) ? (tr[a[j]+1] ? tr[a[j]+1] : r[a[j]+1]) : a[j];
    if(tld[a[j]-1] + ld[a[j]-1]) {
    stl[++top1] = tl[a[j]-1] ? tl[a[j]-1] : l[a[j]-1];
    rint x = stl[top1];
    trd[x] = (trd[x] ? trd[x] : rd[x]) + trd[a[j]], tr[x] = tr[a[j]];
    }
    if(trd[a[j]+1] + rd[a[j]+1]) {
    str[++top2] = tr[a[j]+1] ? tr[a[j]+1] : r[a[j]+1];
    rint x = str[top2];
    tld[x] = (tld[x] ? tld[x] : ld[x]) + tld[a[j]], tl[x] = tl[a[j]];
    }
    cur = max(cur,tld[tr[a[j]]]);
    }
    for(rint j = L;j <= q[i].bel*sqr;++j) tld[a[j]] = trd[a[j]] = tl[a[j]] = tr[a[j]] = 0;
    while(top1) {
    rint x = stl[top1];
    trd[x] = tr[x] = 0;
    top1--;
    }
    while(top2) {
    rint x = str[top2];
    tld[x] = tl[x] = 0;
    top2--;
    }
    ans[q[i].id] = cur;
    }
    for(rint i = 1;i <= m;++i) printf("%d ",ans[i]);
    return 0;
    }

  • 相关阅读:
    my first android test
    VVVVVVVVVV
    my first android test
    my first android test
    my first android test
    ini文件
    ZZZZ
    Standard Exception Classes in Python 1.5
    Python Module of the Week Python Module of the Week
    my first android test
  • 原文地址:https://www.cnblogs.com/2004-08-20/p/14262767.html
Copyright © 2011-2022 走看看