【题解】[LOJ 2736] 「JOISC 2016 Day 3」回转寿司【分块 堆】

题目链接

题意

维护成环的序列 (a)

  • 给定 (A)for i in [l..r]: if a[i]>A: swap(a[i],A),询问 (A) 最后的值。

询问之间显然不独立。

(nleq 4 imes 10^5)(mleq 2.5 imes 10^4),9s。

题解

分块,对于每一块,用一大根堆维护其内部所有的值,用一小根堆维护其 tag。

  • 整块修改:pop 掉最大值,用 (A) 来替换;并将 (A) 扔进 tag;
  • 重构:从左到右扫过去,尝试用 tag 的堆顶更新 (a_i)
#include<bits/stdc++.h>
using namespace std;
int getint(){
    int ans=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9'){
        ans=ans*10+c-'0';
        c=getchar();
    }
    return ans;
}
const int N=4e5+10,B=700;

int a[N];
int blk,bl[N];
int n,m;
struct block{
    int l,r;
    priority_queue<int>val;
    priority_queue<int,vector<int>,greater<int>>tag;
    block():l(0x3f3f3f3f){}
    void rebuild(){
        // while(val.size())val.pop();
        if(tag.empty())return;
        for(int i=l;i<=r;i++){
            if(a[i]>tag.top()){
                int t=tag.top();tag.pop();
                tag.push(a[i]);
                a[i]=t;
            }
        }
    }
    int run(int x){
        tag.push(x);
        val.push(x);
        int t=val.top();
        val.pop();
        return t;
    }
    int run(int l,int r,int x){
        rebuild();
        for(int i=l;i<=r;i++)if(a[i]>x)swap(a[i],x);
        // for(int i=this->l;i<=this->r;i++)val.push(a[i]);
        return x;
    }
};
block b[B];

int main(){
    n=getint(),m=getint();
    blk=sqrt(n);
    int bc=n/blk+1;
    for(int i=1;i<=n;i++)bl[i]=i/blk,
                         b[bl[i]].l=min(b[bl[i]].l,i),
                         b[bl[i]].r=max(b[bl[i]].r,i);
    for(int i=1;i<=n;i++){
        a[i]=getint();
        b[bl[i]].val.push(a[i]);
    }
    while(m--){
        int l=getint(),r=getint(),a=getint();
        if(bl[l]==bl[r]&&l<=r){
            a=b[bl[l]].run(l,r,a);
            printf("%d
",a);
        }else{
            int lb=(bl[l]+1)%bc,rb=bl[r];
            a=b[bl[l]].run(l,b[bl[l]].r,a);
            while(lb!=rb){
                a=b[lb].run(a);
                lb=(lb+1)%bc;
            }
            a=b[bl[r]].run(b[bl[r]].l,r,a);
            printf("%d
",a);
        }
    }
}

原文地址:https://www.cnblogs.com/wallbreaker5th/p/14251720.html