傳送門
題目要求實(shí)現(xiàn)一種數(shù)據(jù)結(jié)構(gòu),支持6種操作: add x,y D:第x個(gè)數(shù)到第y個(gè)數(shù)之間的數(shù)每個(gè)加D; reverse x y:第x個(gè)數(shù)到第y個(gè)數(shù)之間全部數(shù)翻轉(zhuǎn); revolve x y T:第x個(gè)數(shù)到第y個(gè)數(shù)之間的數(shù),向后循環(huán)流動(dòng)T次,即后面T個(gè)數(shù)變成這段子序列的最前面T個(gè),前面的被擠到后面。 Insert x P:在第x個(gè)數(shù)后面插入一個(gè)數(shù)P。 Delete x:刪除第x個(gè)數(shù)。 Min x,y:求第x個(gè)數(shù)到第y個(gè)數(shù)之間的最小數(shù)字。
1.塊狀鏈表。這是很好想而且很好寫的,全是暴力操作。感興趣的可以自己學(xué)習(xí)學(xué)習(xí)。(1400ms)
2.Splay。雖然時(shí)間復(fù)雜度比塊狀鏈表優(yōu)(1087ms,其實(shí)也沒(méi)優(yōu)什么,主要是Splay常數(shù)大),但是代碼特別長(zhǎng)(塊狀鏈表250行,Splay400行)。用Splay主要注意兩點(diǎn),一是打標(biāo)記(Add,Reverse操作),二是提取區(qū)間(即要操作的區(qū)間),提取方法很簡(jiǎn)單,將區(qū)間前一位置于rt,將區(qū)間后一位置于rt的右兒子,那么對(duì)rt右兒子的左兒子操作即可。
主要是Revolve操作有點(diǎn)難寫,下面給出做法:
很顯然是將[r-c+1,r]的區(qū)間提取到[l,r-c]之前,那么先提取前面的區(qū)間,再將l-1置為根節(jié)點(diǎn),將l置為l-1的右兒子,將剛才提取的區(qū)間置為l左兒子即可。
(注意判斷邊界以及及時(shí)更新。。。)
#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 ;
}
#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) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。