• 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;
    }
    
  • 相关阅读:
    GDOI模拟赛Round 1
    Codeforces 241B
    Codeforces 325E
    Codeforces 235E
    Codeforces 293B
    Codeforces 263E
    快速傅里叶变换FFT
    后缀自动机
    NOI2011 Day2
    NOI2014 Day2
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8454815.html
Copyright © 2020-2023  润新知