LibreOJ 6282 数列分块入门 6(在线插入在线查询)

题解:还是分块,将每个块存入vector,然后在插入的时候就是sqrt(n)级的重构,如果块太大了,暴力将这个块拆开.

代码如下:

#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int a[100010],tmp[200010],top;
int n,sz,m;
vector<int> v[1010];

pair<int,int> query(int x)
{
    int pos=1;
    while(x>v[pos].size())
    {
        x-=v[pos].size();
        pos++;
    }
    return make_pair(pos,x-1);
}

void rebuild()
{
    top=0;
    for(int i=1;i<=m;i++)
    {
        for(int j=0;j<v[i].size();j++)
        {
            tmp[++top]=v[i][j];
        }
        v[i].clear();
    }
    int sz2=sqrt(top);
    for(int i=1;i<=top;i++)
    {
        v[(i-1)/sz+1].push_back(tmp[i]);
    }
    m=(top-1)/sz2+1;
}

void insert(int l,int c)
{
    pair<int,int> w=query(l);
    v[w.first].insert(v[w.first].begin()+w.second,c);
    if(v[w.first].size()>20*sz)
    {
        rebuild();
    }
}

int main()
{
    int opt,l,r,c;
    scanf("%d",&n);
    sz=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        v[(i-1)/sz+1].push_back(a[i]);
    }
    m=(n-1)/sz+1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&opt,&l,&r,&c);
        if(!opt)
        {
            insert(l,r);
        }
        else
        {
            pair<int,int> w=query(r);
            printf("%d\n",v[w.first][w.second]);
        }
    }
}

 

posted @ 2018-03-13 19:09  Styx-ferryman  阅读(199)  评论(0编辑  收藏  举报