zoukankan      html  css  js  c++  java
  • LibreOJ 6282. 数列分块入门 6

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

    参考博客:http://www.cnblogs.com/stxy-ferryman/p/8560551.html

    这里如果用数组的话元素右移肯定会超时,如果用链表查询时O(n),n次询问就是O(n^2),然后刚刚又瞟了几眼别人的博客,用分块的话主要好像是有查询位置,插入元素,重构三个操作,查询就是找我们要的这个点在第几层的第几个位置(用的是vector),大概是√n的时间复杂度,因为分成了√n块;然后找到位置之后就可以插入,也是√n,因为插入时要把元素右;然后因为极端数据数据有可能只在一个块里插入元素,所以这个块里面的元素可能远远多于其他块,导致查询时候的时间复杂度变成n,所以要把所有元素重新分块,所以重构的时间复杂度是√n,我看他们都是当一个块里的元素大于10*√n,前面10这个系数应该是可以自己看清况给的,这样的话重构次数是小于√n次的,整体的时间复杂度不太会加,^_^,反正就是比n^2低好多就是了...。

    代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<cstdio>
    #include<string>
    #include<deque> 
    using namespace std;
    typedef long long LL;
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define maxn 100005
    /*struct point{
        int u,w;
    };
    bool operator <(const point &s1,const point &s2)
    {
        if(s1.w!=s2.w)
        return s1.w>s2.w;
        else
        return s1.u>s2.u;
    }*/
    int lump[maxn],a[maxn*2];//lump数组用不到,可以不要,a数组是等下重构时用来存所有元素的 
    vector<int>ve[1010];//存每一层的元素 
    int n,m,k,t,block,Max; //Max是用来存最多有多少层 
    pair<int,int> query(int l)//这个函数是用来寻找第l个元素在第几层第几个,返回一个pair<int,int>类型 
    {                            //它的fist表示层数,second表示第几个,vector里元素从0开始 
        int pos=1;
        while(l>ve[pos].size())
        {
            l-=ve[pos].size();
            pos++;
        }
        return make_pair(pos,l-1);
    }
    void rebuild()//重构操作 
    {
        int top=0;
        for(int i=1;i<=Max;i++)
        {
            for(int j=0;j<ve[i].size();j++)
            {
                a[++top]=ve[i][j];//把所有元素存起来 
            }
            ve[i].clear();//记得清空 
        }
        int block1=sqrt(top);//新的块的大小 
        for(int i=1;i<=top;i++)
        {
            ve[(i-1)/block1+1].push_back(a[i]);
        }
        Max=(top-1)/block+1;
    }
    void insert(int l,int r)
    {
        pair<int,int>w=query(l);//找到位置 
        ve[w.first].insert(ve[w.first].begin()+w.second,r);//插入元素 
        if(ve[w.first].size()>block*10)//如果块太大就重构
        rebuild();
    }
    int find(int l,int r)
    {
        pair<int,int>w=query(r);
        return ve[w.first][w.second];
    }
    int main()
    {
        scanf("%d",&n);
        block=sqrt(n); 
        for(int i=1;i<=n;i++)
        {
            int x; 
            scanf("%d",&x);
            lump[i]=(i-1)/block+1;
            ve[lump[i]].push_back(x);
        }
        Max=(n-1)/block+1;
        for(int j=1;j<=n;j++)
        {
            int op,l,r,c;
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(!op)
            insert(l,r);
            else
            {
                int ans=find(l,r);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    SQL联合更新
    Service Oriented Architecture and WCF
    ubuntu10.4 中安装中文输入法
    QT WINDOWS QTCreator
    QImage,QPixmap,QBitmap,QPicture
    一、Qt Creator的安装和hello world程序的编写
    解决ubuntu打开windows下保存的txt文件中文乱码问题
    Windows+QT+Eclipse+MinGW搭建QT开发环境详细教程
    虚拟机VMware Workstation v6.5官方正式版+汉化补丁+算号器(附安装及使用图解教程)(转)
    决定你是穷人还是富人的12条
  • 原文地址:https://www.cnblogs.com/6262369sss/p/9739292.html
Copyright © 2011-2022 走看看