数列分块入门 6

思路1:直接用vector操作,简单方便,直接水过

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#include <cmath>
#include <stack>
#include <random>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define LD long double
#define LL long long
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define inf 1<<30
#define  ull unsigned long long
const int Mod = 998244353;
const int maxn = 1e6 + 5;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;

        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
int n,k,opt,l,r,c;
vector<int>vt;
int main() 
{
    io;
    n = read();
    for (int i = 1; i <= n; i++) {
        k = read();
        vt.push_back(k);
    }
    for(int i=1;i<=n;i++){
        opt=read();l=read();r=read();c=read();
        if(opt==0)
            vt.insert(vt.begin()+l-1,r);
        else
            cout<<vt[r-1]<<endl;
    }
    return 0;
}

思路2:分块,每一块插入到了一定大小后,对所有块进行重构

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#include <cmath>
#include <stack>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define LD long double
#define LL long long
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define inf 1<<30
#define  ull unsigned long long
const int Mod = 998244353;
const int maxn = 1e6 + 5;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
int n, opt, l, r, c, k, block, m;
int a[maxn];
int v[maxn];//不可以用vector,否则会迷之错误
vector<int>vt[1005];
vector<int>::iterator it;
pair<int, int>find(int b) {//返回第b个在第几块的第几个
    int x = 1;
    while (b > vt[x].size())
        b -= vt[x].size(), x++;
    return make_pair(x, b - 1);//记得减一
}
void rebuild() {//重构
    int tot = 0;
    for (int i = 1; i <= m; i++) {//遍历所有块的所有数
        for (it = vt[i].begin(); it != vt[i].end(); it++) {
            v[++tot] = *it;
        }
        vt[i].clear();//清空块
    }
    int block2 = sqrt(tot);
    m = (tot - 1) / block2 + 1;
    for (int i = 1; i <= tot; i++) {//重新分配
        k = (i - 1) / block2 + 1;
        vt[k].push_back(v[i]);
    }
}
void add(int step, int val) {
    pair<int, int>q = find(step);//返回插入位置
    vt[q.first].insert(q.second + vt[q.first].begin(), val);
    if (vt[q.first].size() > 20 * block)//满足条件重构
        rebuild();
}
int main() {
    scanf("%d", &n);
    block = sqrt(n);
    m = (n - 1) / block + 1;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n; i++) {
        k = (i - 1) / block + 1;
        vt[k].push_back(a[i]);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &opt, &l, &r, &c);
        if (opt == 0) {
            add(l, r);
        } else {
            pair<int, int> t = find(r);//返回位置
            printf("%d\n", vt[t.first][t.second]);
        }
    }
}

 

posted @ 2021-03-29 20:21  夜灯长明  阅读(123)  评论(0编辑  收藏  举报