分塊 學習筆記
阿新 • • 發佈:2018-08-25
rec 數組 cst new count tdi 復雜 i++ str
前言:自從發現分塊的暴力分非常之多以後,我就決心學習它,一直拖到現在。
一、簡介:分塊是一種綜合了鏈表與數組優勢的數據結構,可以平衡兩者查詢與修改的復雜度。
二、以普通平衡樹的題目為例,講解一下具體操作
(0)我們對每一塊維護如下的域
\(nxt:\)下一塊的編號
\(siz:\)當前塊的大小
\(dat[]:\)當前塊的元素
在此題中保證塊外快內的元素同時都是有序的
(1)\(merge(x)\)
作用:將\(x\)與它的下一塊合並
操作:將下一塊的元素接在當前塊的後面,更新當前塊,刪除下一塊
Code:
void Merge(int cur)//合並它和它後面的 { memcpy(t[cur].dat+t[cur].siz,t[Next].dat,t[Next].siz<<2); Size+=t[Next].siz; del(Next); Next=t[Next].nxt; }
附註:有
#define Next t[cur].nxt
#define Size t[cur].siz
關於\(memcpy(void *a,void *b,int \ count)\)
代表把數組\(b\)的\(count\)個字節接到到\(a\)數組傳進來的位置後
(2)\(maintain()\)
作用:維護塊的大小
操作:掃描,將較小的兩個塊合並
Code:
void maintain() { int cur=head; while(Next) { while(Next&&Size+t[cur].siz<=S) Merge(cur); cur=Next; } }
附註:\(S\)大概是\(\sqrt n\)
(3)\(split(cur,pos)\)
作用:將\(cur\)這個塊分成兩個,\(pos\)歸前面
操作:新建塊,處理信息
Code:
void split(int cur,int pos) { if(pos==Size-1) return; int newnode=New(); memcpy(t[newnode].dat,t[cur].dat+pos+1,Size-pos-1<<2); t[newnode].siz=Size-pos-1;Size=pos+1; t[newnode].nxt=Next; Next=newnode; }
以下的操作基本可以按自己喜好來了,我介紹一下自己的
(4)\(Insert(x)\)
作用:插入\(x\)
操作:先分裂,然後搞新塊(避免塊過大),最後\(maintain\)一下
Code:
void Insert(int k)
{
int cur,pos;
pre(cur,pos,k);
split(cur,pos);
int newnode=New();
t[newnode].dat[0]=k,t[newnode].siz=1;
t[newnode].nxt=Next,Next=newnode;
maintain();
}
(5)\(extrack(x)\)
作用:刪除\(x\)
操作:先分裂,然後直接刪,在塊頭的話特判一下
Code:
void extrack(int k)
{
int cur,pos,curn,posn;
pre(curn,posn,k);
cur=curn,pos=posn;
getnext(cur,pos);
split(cur,pos);
if(!pos) {t[curn].nxt=Next,del(cur);return;}
--Size;
maintain();
}
(6)\(pre(\&cur,\&pos,k)\)
作用:就是求前驅
操作:遍歷
Code:
void pre(int &cur,int &pos,int k)
{
cur=head,pos=0;
while(Next&&t[Next].dat[0]<k) cur=Next;
while(pos+1<Size&&t[cur].dat[pos+1]<k) ++pos;
}
(7)\(getnext(\&cur,\&pos)\)
作用:找下一個元素
操作:模擬。
Code:
void getnext(int &cur,int &pos)
{
if(pos<Size-1) {++pos;return;}
pos=0;
if(Next) {cur=Next;return;}
Next=0;
}
三、參考代碼
Code:
#include <cstdio>
#include <cstring>
#define Next t[cur].nxt
#define Size t[cur].siz
const int N=1e5+10;
const int inf=0x7fffffff;
const int S=4e2;
struct node
{
int nxt,siz,dat[S<<1];
}t[S<<1];
int q[N<<1],l=1,r,tot,head,n;
int New()
{
if(l<=r) return q[l++];
else return ++tot;
}
void del(int cur)
{
q[++r]=cur;
}
void Merge(int cur)//合並它和它後面的
{
memcpy(t[cur].dat+t[cur].siz,t[Next].dat,t[Next].siz<<2);
Size+=t[Next].siz;
del(Next);
Next=t[Next].nxt;
}
void maintain()
{
int cur=head;
while(Next)
{
while(Next&&Size+t[cur].siz<=S) Merge(cur);
cur=Next;
}
}
void split(int cur,int pos)
{
if(pos==Size-1) return;
int newnode=New();
memcpy(t[newnode].dat,t[cur].dat+pos+1,Size-pos-1<<2);
t[newnode].siz=Size-pos-1;Size=pos+1;
t[newnode].nxt=Next;
Next=newnode;
}
void pre(int &cur,int &pos,int k)
{
cur=head,pos=0;
while(Next&&t[Next].dat[0]<k) cur=Next;
while(pos+1<Size&&t[cur].dat[pos+1]<k) ++pos;
}
void getnext(int &cur,int &pos)
{
if(pos<Size-1) {++pos;return;}
pos=0;
if(Next) {cur=Next;return;}
Next=0;
}
void suc(int &cur,int &pos,int k)
{
pre(cur,pos,k);
while(t[cur].dat[pos]<=k) getnext(cur,pos);
}
void Insert(int k)
{
int cur,pos;
pre(cur,pos,k);
split(cur,pos);
int newnode=New();
t[newnode].dat[0]=k,t[newnode].siz=1;
t[newnode].nxt=Next,Next=newnode;
maintain();
}
void extrack(int k)
{
int cur,pos,curn,posn;
pre(curn,posn,k);
cur=curn,pos=posn;
getnext(cur,pos);
split(cur,pos);
if(!pos) {t[curn].nxt=Next,del(cur);return;}
--Size;
maintain();
}
int Rank(int k)
{
int cur=head,pos=0,sum=0;
while(t[cur].dat[Size-1]<k) sum+=Size,cur=Next;
while(t[cur].dat[pos]<k) ++pos;
sum+=pos;
return sum;
}
int fRank(int k)
{
int cur=head;
while(Size<k) k-=Size,cur=Next;
return t[cur].dat[k-1];
}
int main()
{
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
scanf("%d",&n);
head=++tot;
t[head].dat[0]=-inf,t[head].siz=1;
for(int op,x,cur,pos,i=1;i<=n;i++)
{
scanf("%d%d",&op,&x);
if(op==1) Insert(x);
else if(op==2) extrack(x);
else if(op==3) printf("%d\n",Rank(x));
else if(op==4) printf("%d\n",fRank(++x));
else if(op==5)
{
pre(cur,pos,x);
printf("%d\n",t[cur].dat[pos]);
}
else
{
suc(cur,pos,x);
printf("%d\n",t[cur].dat[pos]);
}
}
return 0;
}
2018.8.25
分塊 學習筆記