• #6282. 数列分块入门 6


    题目链接:https://loj.ac/problem/6282

    题目描述

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

    输入格式

    第一行输入一个数字 n

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

    接下来输入 n 行询问,每行输入四个数字 opt、lrc,以空格隔开。

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

    若 opt=1,表示询问 ar 的值(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来维护,这样便于实现插入操作,并且往后挪移一位元素的复杂也不会太高。

    如果插入元素太多的话,需要重新分块,因为不重新分块,可能每次都查询这个块,会超时的。
    代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    int a[2*maxn],n,block,maxpos;
    vector<int>v[1010];
    
    pair<int,int> query(int l)//查找第l个元素的位置 
    {
        int cnt=1;
        while(l>v[cnt].size())
        {
            l-=v[cnt].size();
            cnt++;
        }
        return make_pair(cnt,l-1);
    }
    
    void rebuild()//重新分块 
    {
        int cnt=0;
        for(int i=1;i<=maxpos;i++)
        {
            for(int j=0;j<v[i].size();j++)
                a[++cnt]=v[i][j];
            v[i].clear();
        }
        block=sqrt(cnt);//可要可不要,要即是用新的块大小,不要block变化不大,没有关系 
        for(int i=1;i<=cnt;i++)
        {
            v[(i-1)/block+1].push_back(a[i]);
        }
        maxpos=(cnt-1)/block+1;
    }
    
    void insert(int l,int r)//插入 
    {
        pair<int,int> w=query(l);//找到插入的位置 
        v[w.first].insert(v[w.first].begin()+w.second,r);//插入进去 
        if(v[w.first].size()>10*block)//如果插入太多,导致块变得很大,需要重新分块 
            rebuild();
    }
    
    int find(int l,int r)
    {
        pair<int ,int >w=query(r);
        return v[w.first][w.second];
    }
    
    int main()
    {
        scanf("%d",&n);
        block=sqrt(n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            v[(i-1)/block+1].push_back(x);
        }
        maxpos=(n-1)/block+1;//最后的块 
        int opt,l,r,c;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d%d",&opt,&l,&r,&c);
            if(opt==0)
                insert(l,r);
            else
                printf("%d
    ",find(l,r));
        }
    }
     
  • 相关阅读:
    javase程序设计上机作业2
    操作系统课堂笔记——01,操作系统介绍
    javase程序设计上机作业1
    Matlab学习笔记1—MATLAB基础知识
    Matlab学习笔记0—课程导入
    【转】WEB技术发展简史
    leetcode-79-单词搜索(用dfs解决)
    leetcode-78-子集(用bfs解决)
    leetcode-74-搜索二维矩阵
    leetcode-46-全排列
  • 原文地址:https://www.cnblogs.com/xiongtao/p/9792422.html
Copyright © 2020-2023  润新知