LOJ #6282. 数列分块入门 6

 

 

这种题也可以用分块!

用 vector 维护每个整块内的元素,利用内置 insert 函数可以很方便的插入,但不要忘记 vector 是从下标 0 处开始计数

当 vector 内的元素个数大于一定程度时,需要重新分块,因为 vector 插入的复杂度较高

const int N=1e5+5;

    int i,j,k;
    int n,m,t;
    int a[N<<1],block,num; //不断插入元素,数组开大一点
    vector<int> v[N];
    
void build()
{
    block=sqrt(n);
    num=n/block; if(n%block) num++;
    for(int i=1;i<=num;i++){
        int l=(i-1)*block+1;
        int r=min(block*i,n);
        for(int j=l;j<=r;j++) v[i].pb(a[j]);
    }
}

void rebuild()
{
    n=0;
    for(int i=1,len=v[i].size();i<=num;i++){
        for(int j=0;j<len;j++){
            a[++n]=v[i][j];
        }
        v[i].clear();
    }
    build();
}

pii query(int pos)
{
    pii p;
    int cur=1;
    while(v[cur].size()<pos) pos-=v[cur++].size(); //注意判断条件是 <,不是 <=
    return make_pair(cur,pos-1);
}

void update(int pos,int w)
{
    pii p=query(pos);
    int x=p.fr,cnt=p.sc;
    v[x].insert(v[x].begin()+cnt,w); //在 begin+cnt 之前插入 w
    if(v[x].size()>block*10) rebuild();
}

int main()
{
    //IOS;
    while(~sd(n)){
        for(int i=1;i<=n;i++) sd(a[i]);
        build(); m=n;
        while(m--){
            int opt=read(),l=read(),r=read(),w=read();
            if(opt){ pii ans=query(r); pd(v[ans.fr][ans.sc]); }
            else update(l,r);
        }
    }
    //PAUSE;
    return 0;
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页