6.数列分块入门 6
原创
©著作权归作者所有:来自51CTO博客作者wx58438afac3cd5的原创作品,请联系作者获取转载授权,否则将追究法律责任
😊 | Powered By HeartFireY | 分块例题
|
#6282. 数列分块入门 6 - 题目 - LibreOJ (loj.ac)
给出一个长为的数列,以及个操作,操作涉及单点插入,单点询问,数据随机生成。
由于操作涉及单点插入,因此分块的长度会发生变化,因此采用储存每个分块的数据,在更新的时将数据暴力取出更新后放回,对分块结构进行重构。
需要注意的是,并不是每次更新都需要重构,只需要在某个分块的变得非常大时,我们才对分块进行暴力重构。如果变动不大,我们可以近似认为每个分块均摊插入后的。
#include <bits/stdc++.h>
#define ll int
#define pii pair<int, int>
using namespace std;
const int N = 200005;
int blo, lst;
ll a[N], tmp_storage[N];
vector<int> block[N];
void refresh(){
int tot = 0;
for(int i = 1; i <= lst; i++){
for(auto i : block[i]) tmp_storage[++tot] = i;
block[i].clear();
}
blo = sqrt(tot);
for(int i = 1; i <= tot; i++){
int id = (i - 1) / blo + 1;
block[id].push_back(tmp_storage[i]);
}
lst = (tot - 1) / blo + 1;
}
pii query(int pos, int now = 1){
while(pos > block[now].size()){
pos -= block[now].size();
now++;
}
return make_pair(now, pos - 1);
}
void insert(int pos, int x){
pii tmp = query(pos);
block[tmp.first].insert(block[tmp.first].begin() + tmp.second, x);
if(block[tmp.first].size() > 20 * blo) refresh();
}
inline int read(){
int f = 1, x = 0; char s = getchar();
while(s < '0'||s > '9'){ if(s =='-') f = -1; s = getchar(); }
while(s >= '0' && s <= '9'){ x = x * 10 + s - '0'; s = getchar();}
return x *= f;
}
signed main(){
int n = read();; blo = sqrt(n);
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) block[(i - 1) / blo + 1].push_back(a[i]);
lst = (n - 1) / blo + 1;
for(int i = 1; i <= n; i++){
int op = read(), l = read(), r = read(), c = read();
if(op == 0) insert(l, r);
else{
pii tmp = query(r);
printf("%d\n", block[tmp.first][tmp.second]);
}
}
return 0;
}