• loj #6282. 数列分块入门 6


    #6282. 数列分块入门 6

    题目描述

    给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及单点插入,单点询问,数据随机生成。

    输入格式

    第一行输入一个数字 nnn。

    第二行输入 nnn 个数字,第 i 个数字为 aia_iai​​,以空格隔开。

    接下来输入 nnn 行询问,每行输入四个数字 optmathrm{opt}opt、lll、rrr、ccc,以空格隔开。

    若 opt=0mathrm{opt} = 0opt=0,表示在第 lll 个数字前插入数字 rrr (ccc 忽略)。

    若 opt=1mathrm{opt} = 1opt=1,表示询问 ara_rar​​ 的值(lll 和 ccc 忽略)。

    输出格式

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

    样例

    样例输入

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

    样例输出

    2
    3

    数据范围与提示

    对于 100% 100\%100% 的数据,1≤n≤100000,−231≤others 1 leq n leq 100000, -2^{31} leq mathrm{others}1n100000,231​​others、ans≤231−1 mathrm{ans} leq 2^{31}-1ans231​​1。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxn 2010
    using namespace std;
    int n,block,p,T,a[maxn][maxn],b[maxn][maxn],len[maxn];
    void reset(){
        int y=0,k=p/block,ll=0;
        if(p%block!=0)k++;
        p+=block;block=sqrt(p);
        T=0;
        for(int i=1;i<=k;i++)
            for(int j=1;j<=len[i];j++){
                y++;
                int kk=(y-1)/block+1;
                b[kk][++ll]=a[i][j];
                a[i][j]=0;
                if(ll==block)ll=0;
            }
        k=p/block;
        if(p%block!=0)k++;
        for(int i=1;i<=k;i++){
            if(i!=k||p%block==0)len[i]=block;
            else len[i]=p-block*block;
            for(int j=1;j<=len[i];j++)a[i][j]=b[i][j];
        }
    }
    int main(){
        scanf("%d",&n);p=n;block=sqrt(n);
        for(int i=1;i<=n;i++){
            int k=(i-1)/block+1;
            int x;scanf("%d",&x);
            a[k][++len[k]]=x;
        }
        T=0;
        for(int i=1;i<=n;i++){
            int op,l,r,c;
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(op==0){
                int k=0,t;
                for(t=1;t<=block;t++){
                    if(k+len[t]>=l)break;
                    k+=len[t];
                }
                len[t]++;
                for(int j=len[t];j>=l-k+1;j--)
                    a[t][j]=a[t][j-1];
                a[t][l-k]=r;
                T++;
                if(T==block)reset();
            }
            else {
                int k=0,t;
                for(t=1;t<=block;t++){
                    if(k+len[t]>=r)break;
                    k+=len[t];
                }
                printf("%d
    ",a[t][r-k]);
            }
        }
        return 0;
    }
  • 相关阅读:
    C# 序列化技术详解《转》
    DataGridView中的DataGridViewComboBoxColumn使用浅析
    取EXCEL文件的3种方法
    教你几种在SQLServer中删除重复数据方法
    事件浅析
    迭代委托链
    C#调用耗时函数时显示进度条浅探
    启动公告【过时】
    在Web应用中接入微信支付的流程之极简清晰版
    VBoxManage: error: Cannot register the hard disk 解决办法
  • 原文地址:https://www.cnblogs.com/thmyl/p/8966123.html
Copyright © 2020-2023  润新知