LOJ.6282.数列分块入门6(块状链表/分块)

题目链接
1.分块(vector)+重构

//直接上vector(本机还是比较慢的...) 某块size较大时O(n)重构 
//注意细节 
#include <cmath>
#include <cstdio>
#include <cctype>
#include <vector>
#define gc() getchar()
#define pb push_back
typedef long long LL;
const int N=1e5+5;

int n,size,tmp[N<<1],bel;
std::vector<int> v[500];
std::vector<int>::iterator it;

inline int read()
{
	int now=0,f=1;register char c=gc();
	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now*f;
}
inline int Get_Pos(int &p)
{
	for(int i=1; i<=bel; ++i)
		if((p-=v[i].size())<=0) {p+=v[i].size(); return i;}
}
void Rebuild()
{
	int tot=0;
	for(int i=1; i<=bel; ++i)
	{
		for(it=v[i].begin(); it!=v[i].end(); ++it) tmp[++tot]=*it;
		v[i].clear();
	}
	size=sqrt(tot);
	for(int i=1; i<=tot; ++i) bel=(i-1)/size+1, v[bel].pb(tmp[i]);
}
void Insert(int p,int val)
{
	int id=Get_Pos(p);
	v[id].insert(v[id].begin()+p-1,val);
	if(v[id].size()>size*15) Rebuild();
}

int main()
{
	n=read(), size=sqrt(n);
	for(int i=1; i<=n; ++i) bel=(i-1)/size+1,v[bel].pb(read());
	for(int opt,l,r,c,id,i=1; i<=n; ++i)
	{
		opt=read(),l=read(),r=read(),c=read();
		if(opt) id=Get_Pos(r),printf("%d
",v[id][r-1]);
		else Insert(l,r);
	}
	return 0;
}

2.块状链表

#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=1e5+5;

int n,size,H[N],nxt[N],nxtv[N<<1],A[N<<1],sz[N];//二倍数组!mdzzC++数组越界各种奇葩错误(这指针无语) 

inline int read()
{
	int now=0,f=1;register char c=gc();
	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now*f;
}
inline int New_Node()
{
	static int cnt=n;
	return ++cnt;
}
inline int New_Block()
{
	static int cnt=(n-1)/size+1;
	return ++cnt;
}
void Init()
{
	for(int i=1; i<=n; ++i) A[i]=read();
	int tot=(n-1)/size+1;
	H[0]=1;
	for(int now=0,i=1; i<tot; ++i)//块整体的链表 
		H[i]=(i-1)*size+1, nxt[i]=i+1, sz[i]=size;
	sz[tot]=n-(tot-1)*size, H[tot]=(tot-1)*size+1;
	for(int i=1,tmp=i*size; i<=tot; tmp=++i*size)//块内链表 
		for(int j=(i-1)*size+1; j<tmp; ++j)
			nxtv[j]=j+1;
}
int Get_Pos(int &p)
{
	for(int i=H[0]; i; i=nxt[i])
		if((p-=sz[i])<=0) {p+=sz[i]; return i;}
}
int Query(int p)
{
	int id=Get_Pos(p);
	for(int i=H[id]; i; i=nxtv[i])
		if(!--p) return A[i];
}
void Insert(int p,int v)
{
	int id=Get_Pos(p),pos=New_Node();
	A[pos]=v, ++sz[id];
//	printf("I pos:%d id:%d p:%d size:%d stdsz:%d sz[id]:%d
",pos,id,p,size*(id-1)+p,size,sz[id]);
	if(!p) nxtv[pos]=H[id], H[id]=pos;
	else
		for(int i=H[id]; i; i=nxtv[i])
			if(!--p) {nxtv[pos]=nxtv[i], nxtv[i]=pos; break;}
	if(sz[id] > size<<1)//2倍比较合适 
	{
		p=size;
		for(int i=H[id]; i; i=nxtv[i])
			if(!(--p)) {pos=nxtv[i], nxtv[i]=0; break;}
		int posb=New_Block();
		H[posb]=pos, nxt[posb]=nxt[id], nxt[id]=posb, sz[posb]=sz[id]-size, sz[id]=size;
	}
}
//void Print()
//{
//	puts("Output:");
//	for(int i=H[0]; i; i=nxt[i])
//		for(int j=H[i]; j; j=nxtv[j])
//			printf("%d ",A[j]);
//	putchar('
');
//}

int main()
{
	n=read(), size=sqrt(n);
	Init();
	for(int opt,l,r,c,i=1; i<=n; ++i)
	{
		opt=read(),l=read(),r=read(),c=read();
		if(opt) printf("%d
",Query(r));
		else Insert(l-1,r);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/SovietPower/p/8454815.html