[LOJ] 分块九题 6

单点插入,单点查询。

优化了的链表。

链表老写错,干脆用vector,也不算慢。

注意链表退化的问题,及时(比如操作根号n次)就重新建块,实测速度可以提高一倍,这还是数据随机的情况,若涉及大量同一位置插入,会让分块大大退化。

build没必要写两个。

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cmath>
#include<cstring>
#include<cctype>
#include<vector>
#define vit vector<int>::iterator
using namespace std;

const int MAXN=500005;

inline int read_d(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c)) f=c=='-'?-1:1;
    while(isdigit(c)){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret*f;
}

int n;
int block,num;
vector<int> lis[1000];
int a[MAXN];

void build(int pos){
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=num;i++){
        for(vit it=lis[i].begin();it!=lis[i].end();it++)
            a[++pos]=*it;
        lis[i].clear();
    }
    for(int i=1;i<=num;i++)
        for(int j=(i-1)*block+1;j<=i*block&&j<=n;j++)
            lis[i].push_back(a[j]);     
} 

int query(int x){
    int pos=1,siz=0;
    while(siz+lis[pos].size()<x) siz+=lis[pos++].size();
    return lis[pos][x-siz-1];
}

int tim;
void updata(int x,int w){
    int pos=1,siz=0;tim++;n++;
    while(siz+lis[pos].size()<x) siz+=lis[pos++].size();
    lis[pos].insert(lis[pos].begin()+x-siz-1,w); 
    if(tim>block) build(0),tim=0;
}

int main(){
    n=read_d();
    for(int i=1;i<=n;i++) a[i]=read_d();
    build(n);
    int T=n;
    for(int i=1;i<=T;i++){
        int q=read_d(),x=read_d(),y=read_d(),z=read_d();
        if(q==0) updata(x,y);
        else printf("%d\n",query(y));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/gh0stcai/article/details/79928830
今日推荐