LibreOj6282 数列分块入门 6 单点插入+单点询问

    xiaoxiao2025-03-18  31

    数列分块入门 6

    链接:LibreOj6282

    题目描述

    给出一个长为n的数列,以及n个操作,操作涉及单点插入,单点询问。

    输入格式

    第一行输入一个数字n。

    第二行输入n个数字,第i个数字为 a[i],以空格隔开。

    接下来输入n行询问,每行输入四个数字op、l、r、c,以空格隔开。

    若 op==0,表示在第l个数字前插入数字r( c忽略)。

    若 op==1,表示询问a[r]的值( l 和c忽略)。

    输出格式

    对于每次询问,输出一行一个数字表示答案。

    样例输入

    4 1 2 2 3 0 1 3 1 1 1 4 4 0 1 2 2 1 1 2 4

    样例输出

    2 3

    分析:

    之前分块题目得数据都是存放同一个数组上得。 这题得用vector(或者其他?)分开存放每个块得数据。 这样得好处是每个块可以使用stl得很多操作。就比如这题的插入。 但是一个块如果一直插入数据,块的数据量会一直增大。 所以在块的数据多大的时候(比如大于三个block大小),我们就重新分块。 这样能保证之后的操作耗时不会太大。

    ps:不过这题不重新分块也能过(但是会花两倍多时间)。

    完整代码:

    #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<vector> #include<set> #include<queue> #include<stack> #include<map> #include<string> #include<algorithm> #include<sstream> #include<memory> #include<utility> #include<functional> #include<iterator> typedef long long ll; const int inf=0x3f3f3f3f; const int inn=0x80808080; using namespace std; const int maxm=1e5+5; int belong[maxm]; int mark[maxm];//每一块的长度 int a[maxm*2];//用于重构的时候临时存放所有数据 int block,num; int n;//最开始数据个数 int all;//数据总个数 vector<int>temp[maxm]; void build(){ block=sqrt(n);//这个地方用all来分好像也可以啊,不太懂 num=all/block;//新的块数 if(all%block)num++; for(int i=1;i<=n;i++){ belong[i]=(i-1)/block+1;//这题belong用处不大,可简化, temp[belong[i]].push_back(a[i]); mark[belong[i]]++; } } void reset(){ int cnt=1; for(int i=1;i<=num;i++){ int len=temp[i].size(); for(int j=0;j<len;j++){ a[cnt++]=temp[i][j]; } temp[i].clear(); mark[i]=0; } } void update(int x,int val){ int now=1; while(x>mark[now]){ x-=mark[now]; now++; } temp[now].insert(temp[now].begin()+x-1,val); mark[now]++; all++; if(mark[now]>2*block){ reset(); build(); } } void ffind(int x){ int now=1; while(x>mark[now]){ x-=mark[now]; now++; } printf("%d\n",temp[now][x-1]); } int main(){ scanf("%d",&n); all=n; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(); for(int i=1;i<=n;i++){ int d,x,y,c; scanf("%d%d%d%d",&d,&x,&y,&c); if(d==0){ update(x,y); }else{ ffind(y); } } return 0; }
    最新回复(0)