日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poj3580:SuperMemo(块状链表/Splay)

發(fā)布時間:2023/12/16 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj3580:SuperMemo(块状链表/Splay) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

傳送門

  • 題意:

題目要求實現(xiàn)一種數(shù)據(jù)結(jié)構(gòu),支持6種操作:
add x,y D:第x個數(shù)到第y個數(shù)之間的數(shù)每個加D;
reverse x y:第x個數(shù)到第y個數(shù)之間全部數(shù)翻轉(zhuǎn);
revolve x y T:第x個數(shù)到第y個數(shù)之間的數(shù),向后循環(huán)流動T次,即后面T個數(shù)變成這段子序列的最前面T個,前面的被擠到后面。
Insert x P:在第x個數(shù)后面插入一個數(shù)P。
Delete x:刪除第x個數(shù)。
Min x,y:求第x個數(shù)到第y個數(shù)之間的最小數(shù)字。

  • 題解

1.塊狀鏈表。這是很好想而且很好寫的,全是暴力操作。感興趣的可以自己學(xué)習(xí)學(xué)習(xí)。(1400ms)

2.Splay。雖然時間復(fù)雜度比塊狀鏈表優(yōu)(1087ms,其實也沒優(yōu)什么,主要是Splay常數(shù)大),但是代碼特別長(塊狀鏈表250行,Splay400行)。用Splay主要注意兩點,一是打標記(Add,Reverse操作),二是提取區(qū)間(即要操作的區(qū)間),提取方法很簡單,將區(qū)間前一位置于rt,將區(qū)間后一位置于rt的右兒子,那么對rt右兒子的左兒子操作即可。

主要是Revolve操作有點難寫,下面給出做法:

很顯然是將[r-c+1,r]的區(qū)間提取到[l,r-c]之前,那么先提取前面的區(qū)間,再將l-1置為根節(jié)點,將l置為l-1的右兒子,將剛才提取的區(qū)間置為l左兒子即可。

(注意判斷邊界以及及時更新。。。)

  • Code1(塊狀鏈表):1454MS
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; inline int read(); const int N = 1e5 + 5, INF = 0x7fffffff, SIZEINT = sizeof(int); const int SQRTN = 500, B = 1000, SMIN = SQRTN / 2, SMAX = SQRTN * 2; int n, m, a[N]; typedef struct Block* PBlock; typedef struct List* PList; struct Block { int a[SQRTN * 5]; int size, tag, rev, ans; inline void calc() { tag = rev = 0; ans = INF; for (int i = 0; i < size; ++i) if (a[i] < ans) ans = a[i]; } inline void downdate() { if (tag != 0){ for (int i = 0; i < size; ++i)a[i] += tag; tag = 0; } if (rev){ rev = 0; for (int i = 0; i << 1 < size; ++i){ int t = a[i]; a[i] = a[size - i - 1]; a[size - i - 1] = t; } } } }used[B]; PBlock pool, *top, unused[B]; struct List { PBlock a; PList last, next; }USED[B]; PList head, tail, POOL, *TOP, UNUSED[B]; inline PBlock newBlock() { if (top != unused) return *--top; return pool++; } inline void delBlock(PBlock x) { *top++ = x; } inline PList newList() { if (TOP != UNUSED) return *--TOP; return POOL++; } inline void delList(PList x) { *TOP++ = x; } inline void Build(int *a, const int &n, PList *h, PList *t) { for (int i = 0; i < n; i += SQRTN) { PList p = newList(); p->a = newBlock(); p->a->size = i + SQRTN < n ? SQRTN : n - i; memcpy(p->a->a, a + i, SIZEINT * p->a->size); p->a->calc(); p->last = *t; p->next = NULL; if (*t != NULL) (*t)->next = p; else *h = p; *t = p; } } inline void merge(PList x) { PList p = x->next; x->a->downdate(); p->a->downdate(); memcpy(x->a->a + x->a->size, p->a->a, SIZEINT * p->a->size); x->a->size += p->a->size; x->a->calc(); x->next = p->next; if (p->next) p->next->last = x; else tail = x; delBlock(p->a); delList(p); } inline void split(PList x, const int &n) { PList p = newList(); p->a = newBlock(); x->a->downdate(); p->a->size = x->a->size - n; memcpy(p->a->a, x->a->a + n, SIZEINT * p->a->size); x->a->size = n; x->a->calc(); p->a->calc(); p->next = x->next; if (x->next) x->next->last = p; else tail = p; x->next = p; p->last = x; } inline void Balance() { for (PList p = head; p; p = p->next) { while (p != tail && p->a->size < SMIN)merge(p); if (p->a->size > SMAX)split(p, SQRTN); } } inline void Delete(PList x) { if (x->last != NULL) x->last->next = x->next; else head = x->next; if (x->next != NULL) x->next->last = x->last; else tail = x->last; delBlock(x->a); delList(x); } inline PList findl(int n) { PList p = head; for (; n > p->a->size; p = p->next) n -= p->a->size; if (n != 1) { split(p, n - 1); p = p->next; } return p; } inline PList findr(int n) { PList p = head; for (; n > p->a->size; p = p->next) n -= p->a->size; if (n != p->a->size) split(p, n); return p; } inline void Init() { pool = used; POOL = USED; top = unused; TOP = UNUSED; head = tail = NULL; } char ch; inline int read() { int res = 0, sgn = 0; while (ch = getchar(), ch < '0' || ch > '9') if (ch == '-') sgn = 1; res = ch - 48; while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48; return sgn ? -res : res; } int main() { Init(); n = read(); for (int i = 0; i < n; ++i) a[i] = read(); Build(a, n, &head, &tail); m = read(); char type; int l, r, v; PList fr, en, t; PBlock tmp; while (m--) { Balance(); while (type = getchar(), type < 'A' || type > 'Z'); if (type == 'A') { l = read(); r = read(); v = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); for (en = en->next; fr != en; fr = fr->next) { fr->a->tag += v; fr->a->ans += v; } } else if (type == 'I') { l = read(); r = read(); fr = findr(l); fr->a->downdate(); fr->a->a[fr->a->size++] = r; if (r < fr->a->ans) fr->a->ans = r; } else if (type == 'D') { l = read(); fr = findl(l); if (fr->a->size != 1) split(fr, 1); Delete(fr); } else if (type == 'M') { l = read(); r = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); int ans = INF; for (en = en->next; fr != en; fr = fr->next) if (fr->a->ans < ans) ans = fr->a->ans; printf("%d\n", ans); } else { getchar(); getchar(); type = getchar(); if (type == 'E') { l = read(); r = read(); if (l > r) swap(l, r); fr = findl(l); en = findr(r); while (fr != en && fr != en->next) { fr->a->rev ^= 1; en->a->rev ^= 1; tmp = fr->a; fr->a = en->a; en->a = tmp; fr = fr->next; en = en->last; } if (fr == en) fr->a->rev ^= 1; } else { l = read(); r = read(); if (l > r) swap(l, r); v = read() % (r - l + 1); if (v == 0 || l == r) continue; v = r - l + 1 - v; fr = findl(l); en = findr(r); for (t = fr; v > t->a->size; t = t->next) v -= t->a->size; if (v != t->a->size) { split(t, v); if (en == t) en = en->next; } PList p1 = fr->last, p2 = fr, p3 = t, p4 = t->next, p5 = en, p6 = en->next; if (p1 != NULL) { p1->next = p4; p4->last = p1; } else head = p4, p4->last = NULL; if (p6 != NULL){ p6->last = p3; p3->next = p6; } else tail = p3, p3->next = NULL; p5->next = p2; p2->last = p5; } } } return 0; }
  • Code2(Splay):1047ms
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int Maxn=2e5+50; const int INF=0x3f3f3f3f; inline int read() {char ch=getchar();int i=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}return i*f; }struct node {node *fa,*lc,*rc;int val,taga,tagr,mn,sze;node():fa(NULL),lc(NULL),rc(NULL){}inline void upt(){sze=(lc?lc->sze:0)+(rc?rc->sze:0)+1;mn=min(val,min(lc?lc->mn:INF,rc?rc->mn:INF));} }POOL[Maxn],*pool=POOL,*rt,*que[Maxn];int n,m,a[Maxn],bg,ed; char ch[10];inline void add(node *now,int val) {now->val+=val;now->mn+=val;now->taga+=val; }inline void addr(node *now) {swap(now->lc,now->rc);now->tagr^=1; }inline node* newnode(int val) {++pool;pool->val=val;pool->mn=val;pool->sze=1;return pool; }inline void build(node *&now,int l,int r) {int mid=(l+r)>>1;now=newnode(a[mid]);if(l<mid)build(now->lc,l,mid-1);if(r>mid)build(now->rc,mid+1,r);if(now->lc)now->lc->fa=now;if(now->rc)now->rc->fa=now;now->upt(); }inline void pushdown(node *now) {if(now->taga){if(now->lc){now->lc->mn+=now->taga;now->lc->val+=now->taga;now->lc->taga+=now->taga;}if(now->rc){now->rc->mn+=now->taga;now->rc->val+=now->taga;now->rc->taga+=now->taga;}now->taga=0;}if(now->tagr){if(now->lc){swap(now->lc->lc,now->lc->rc);now->lc->tagr^=1;}if(now->rc){swap(now->rc->lc,now->rc->rc);now->rc->tagr^=1;}now->tagr^=1; } }inline node* find(node *now,int k) {pushdown(now);now->upt();if((now->lc?now->lc->sze:0)==k-1)return now;else if((now->lc?now->lc->sze:0)>k-1)return find(now->lc,k);else return find(now->rc,k-(now->lc?now->lc->sze:0)-1); }inline void Rotate(node *x) {node *y=x->fa,*z=y->fa;y->fa=x;x->fa=z;if(z){((z->lc==y)?(z->lc):(z->rc))=x;}if(y->lc==x){node* b=x->rc;if(b)b->fa=y;y->lc=b;x->rc=y;}else{node* b=x->lc;if(b)b->fa=y;y->rc=b;x->lc=y;}y->upt();x->upt(); }inline bool which(node* x) {return x->fa->lc==x; }inline void Splay(node* x,node* tar=NULL) {que[ed=1]=x;for(node* y=x;y!=rt;y=y->fa)que[++ed]=y->fa;for(int i=ed;i>=1;i--){node* y=que[i];pushdown(y);}while(x->fa!=tar){node* y=x->fa,*z=y->fa;if(z!=tar){if(which(x)^which(y))Rotate(x);else Rotate(y);}Rotate(x);}if(!tar)rt=x; }inline node* split(int l,int r) {if(l&&r<=n){node *t1=find(rt,l);node *t2=find(rt,r);Splay(t1);Splay(t2,rt);node *t3=t2->lc;t2->lc=NULL;t2->upt();t3->fa=NULL;return t3;}else if(!l){node *t2=find(rt,r);Splay(t2);node *t3=t2->lc;t2->lc=NULL;t2->upt();t3->fa=NULL;return t3;}else{node *t1=find(rt,l);Splay(t1);node *t3=t1->rc;t3->fa=NULL;t1->rc=NULL;t1->upt();return t3;} }int buf[50]; inline void W(int x) {if(!x){putchar('0');return;}if(x<0)putchar('-'),x=-x;while(x)buf[++buf[0]]=x%10,x/=10;while(buf[0])putchar('0'+buf[buf[0]--]);return; }int main() {n=read();for(int i=1;i<=n;i++){a[i]=read();}build(rt,1,n);m=read();while(m--){scanf("%s",ch+1);if(ch[1]=='A'){int l=read(),r=read(),v=read();if(l==1&&r==n)add(rt,v);else if(l==1){node* t2=find(rt,r+1);Splay(t2);add(rt->lc,v);rt->upt();}else if(r==n){node* t1=find(rt,l-1);Splay(t1);add(rt->rc,v);rt->upt();}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);add(t2->lc,v);t2->upt();t1->upt();}}else if(ch[1]=='I'){int x=read(),y=read();if(x!=0&&x!=n){node* t1=find(rt,x);node* t2=find(rt,x+1);Splay(t1);Splay(t2,rt);t2->lc=newnode(y);t2->lc->fa=t2;t2->upt();t1->upt();n++;}else if(x!=0){node* t1=find(rt,x);Splay(t1);t1->rc=newnode(y);t1->rc->fa=t1;t1->upt();n++;}else{node* t2=find(rt,x+1);t2->lc=newnode(y);t2->lc->fa=t2;t2->upt();n++;} }else if(ch[1]=='D'){int pos=read();if(pos!=1&&pos!=n){node* t1=find(rt,pos-1);node* t2=find(rt,pos+1);Splay(t1);Splay(t2,rt);t2->lc->fa=NULL;t2->lc=NULL;t2->upt();rt->upt();n--;}else if(pos!=1){node* t1=find(rt,pos-1);Splay(t1);t1->rc->fa=NULL;t1->rc=NULL;t1->upt();n--;}else{node* t2=find(rt,pos+1);Splay(t2);t2->lc->fa=NULL;t2->lc=NULL;t2->upt();n--;}}else if(ch[1]=='M'){int l=read(),r=read();if(l==1&&r==n)W(rt->mn),putchar('\n');else if(l==1){node* t2=find(rt,r+1);Splay(t2);W(rt->lc->mn),putchar('\n');}else if(r==n){node* t1=find(rt,l-1);Splay(t1);W(rt->rc->mn),putchar('\n');}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);W(t2->lc->mn),putchar('\n');}}else if(ch[4]=='E'){int l=read(),r=read();if(l==1&&r==n)addr(rt);else if(l==1){node* t2=find(rt,r+1);Splay(t2);addr(rt->lc);}else if(r==n){node* t1=find(rt,l-1);Splay(t1);addr(rt->rc);}else {node* t1=find(rt,l-1);node* t2=find(rt,r+1);Splay(t1);Splay(t2,rt);addr(t2->lc);}}else{int x=read(),y=read(),c=read();int l=(y-x+1);c%=l;if(c==0)continue;node* t1=split(y-c,y+1);if(x!=1){node* t2=find(rt,x-1);node* t3=find(rt,x);Splay(t2);Splay(t3,rt);t3->lc=t1;t1->fa=t3;t3->upt();t2->upt();}else{node* t3=find(rt,x);Splay(t3);t3->lc=t1;t1->fa=t3;t3->upt();}}} }

總結(jié)

以上是生活随笔為你收集整理的poj3580:SuperMemo(块状链表/Splay)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。