1. 程式人生 > 其它 >LOJ 數列分塊入門 6

LOJ 數列分塊入門 6

\(\text{Solution}\)

涉及到插入,分塊需要動態維護塊內的元素及相對位置
於是妙用 \(\text{vector}\)
學到了 \(insert\) 操作,在某個迭代器前插入元素
這樣我們對元數列分塊,塊長 \(\sqrt n\)
每個塊用 \(\text{vector}\) 維護
插入時一塊一塊地找到合適塊的合適位置,用 \(insert\) 插入容器(複雜度與插入位置到末元素長度線性相關)

\(\text{Solution}\)

#include <cstdio> 
#include <vector>
#include <cmath>
#define re register
using namespace std;

const int N = 1e5 + 5;
int n, a[N], st[N], ed[N], id[N];
vector<int> Q[N];

inline void prepare()
{
	int num = sqrt(n);
	for(re int i = 1; i <= num; i++)
	{
		st[i] = ed[i - 1] + 1, ed[i] = (i == num ? n : ed[i - 1] + n / num);
		for(re int j = st[i]; j <= ed[i]; j++) id[j] = i;
	}
	for(re int i = 1; i <= n; i++) Q[id[i]].push_back(a[i]);
}
inline void Insert(int x, int v)
{
	int cur = 0, p = 0;
	while (cur < x) cur += Q[++p].size();
	Q[p].insert(Q[p].begin() + Q[p].size() - cur + x - 1, v);
}
inline int Query(int x)
{
	int cur = 0, p = 0;
	while (cur < x) cur += Q[++p].size();
	return Q[p][Q[p].size() - cur + x - 1];
}

int main()
{
	scanf("%d", &n);
	for(re int i = 1; i <= n; i++) scanf("%d", &a[i]);
	prepare();
	for(re int i = 1, op, l, r, c; i <= n; i++)
	{
		scanf("%d%d%d%d", &op, &l, &r, &c);
		if (!op) Insert(l, r);
		else printf("%d\n", Query(r));
	}
}