LOJ #6282. 数列分块入门 6

版权声明:欢迎转载 https://blog.csdn.net/yandaoqiusheng/article/details/88745431

题目链接:传送门
支持单点插入,单点询问

一个短短的splay就好了
可是我们是来学分块的
这里只有网上的普遍做法
还是用vector维护每个块内的维护
插入的时候找到在哪个块内
如果插入过多导致块很大就全部重构

/**
 * @Date:   2019-03-22T16:21:58+08:00
 * @Last modified time: 2019-03-22T16:48:25+08:00
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define A 1000010
#define B 2010

using namespace std;
typedef long long ll;
int n, m, kn, bl[A], sta[A], a, b, c, opt;
vector<int> v[A];
pair<int, int> find(int fr, int pos = 1) {
    while (fr > v[pos].size()) fr -= v[pos].size(), pos++;
    return make_pair(pos, fr - 1);
}
void insert(int l, int r) {
    pair<int, int> fr = find(l);
    v[fr.first].insert(v[fr.first].begin() + fr.second, r);
    if (v[fr.first].size() > m * 10) {
        int top = 0;
        for (int i = 1; i <= kn; i++) {
            for (auto it = v[i].begin(); it != v[i].end(); it++) sta[++top] = *it;
            v[i].clear();
        }
        int m = sqrt(top);
        kn = (top - 1) / m + 1;
        for (int i = 1; i <= top; i++) bl[i] = (i - 1) / m + 1, v[bl[i]].push_back(sta[i]);
    }
}

int main(int argc, char const *argv[]) {
    cin >> n; m = sqrt(n); kn = (n - 1) / m + 1;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a);
        bl[i] = (i - 1) / m + 1;
        v[bl[i]].push_back(a);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &opt, &a, &b, &c);
        if (!opt) insert(a, b);
        else {pair<int, int> ff = find(b); printf("%d\n", v[ff.first][ff.second]);}
    }
}

猜你喜欢

转载自blog.csdn.net/yandaoqiusheng/article/details/88745431