【pku3580】SuperMemo(Splay維護區間資訊)

來源:互聯網
上載者:User

一向對資料結構不感冒,這次有所改觀

盾哥對SPLAY 的崇拜使我也開始對這種感覺還比較好用的資料結構產生了興趣

先分析下SPLAY的特點:

      1.它能維護一個序列,動態地支援一些操作(主要是區間型操作),任意時刻它的中序遍曆都是當前序列,這棵樹其實是以位置為“序”的

      2.它可以通過提根操作完成區間型操作,這裡要用到類似與線段樹的LAZY標記,更基本的操作就是旋轉

      3.可擴充性非常好,支援非常多的操作,感覺上線段樹能搞定的,splay基本上都沒什麼問題

      4.它的常數因子非常大,O(logN)真的只是“理論”複雜度

      5.標準的splay有一大堆旋轉和一大堆特判,編程複雜度奇高無比,其實不實用。個人感覺裸提根(就是只用樸素的左旋右旋)也還不錯,對於編程速度要求很高的各大oi比賽中,較低的編程複雜度可能會更合適

      6.初始的建樹如果想偷懶就直接建成一條鏈,然後一頓亂旋幾下,而要求高點可能就要建成一棵完全二叉樹了

      7.由於每個點攜帶的資訊不多,空間上比線段樹什麼的稍微好點

大概就這樣吧,可以看到,splay還是相當不錯的,下面接著看這道題

題目大意:

     維護一個序列,支援下列操作:

    1.插入刪除;

     2.翻轉一段選定的序列;

     3.交換兩段相鄰的序列;

     4.一段全部增加k;

     5.詢問一段的最小值。

分析:

     看到一大堆的操作就應該想到是到資料結構題,由於要完成區間型操作,可以會先想到線段樹,但動態插入和刪除貌似用線段樹不好搞定,怎麼辦?splay這種強大的資料結構便能讓我們脫離苦海,駛向ac的彼岸

演算法:

     用splay維護這個序列(先搞個極小極大點),對於每個操作:

     1.插入 j 到 i 後面:

       首先把i提根,在建立節點 j,使得r[j]=r[i];r[i]=j; 再維護j,i的資訊即可;

     2.刪除i:

       首先把i提根,再把 i+1提根,接著把 l[i+1]=l[i],維護i+1,這樣 i 就被刪除了;

     3.翻轉(增加)區間[a,b]:

       先把a-1提根,再把b+1提根,這時候,以r[l[root]]就是我們要的區間,再用線段樹的lazy思想,把標記放上去並維護就可以了;

     4.交換相鄰兩段序列[a,b],[b+1,c](所謂的revolve其實就是這個,自己想一想):

       這個操作稍微麻煩一點,先把b提根,再把a-1提為b的左兒子,接著把c+1提為b的右兒子,這時把l[r[root]](即區間[b+1,c])作為l[root]的右兒子,而原來的右兒子作為root的左兒子。此時發現root和原來的l[root]這顆子樹中斷連線了,我們需要把此時以root為根的樹的最小的點提出來作為根,再把原來的l[root]置為 root‘ 的左兒子,操作完成。

    編寫的時候還是出現了一些問題的,要不會像盾哥一樣調到晚上一點多(結果第二天遲到了),如:

           1.min數組在標記下放的是後可以同加同減,不用再從下面更新了,更新也是錯的。

           2.標記下方完後清空。

           3.因為一開始就建立了n+2個點,所以記總點數一開始即為n+2

    好了,只用了145行就搞定,而且交這道題時是1遍ac,小小的爽了一把。

代碼:

 program syj_splay;<br />const<br /> maxn=100000+5;<br /> oo=maxlongint shr 1;<br />var n,root,task:longint;<br /> a,son,l,r,b1,b2,mi:array[0..maxn+maxn]of longint;<br />function min(x,y:longint):longint;<br />begin<br /> if x<y then min:=x<br /> else min:=y;<br />end;<br />procedure init;<br />var i:longint;<br />begin<br /> readln(n);<br /> root:=n+2;<br /> for i:=2 to n+1 do begin<br /> readln(a[i]);l[i]:=i-1;son[i]:=i;mi[i]:=a[i];<br /> end;<br /> l[n+2]:=n+1;son[1]:=1;son[n+2]:=n+2;mi[0]:=oo;mi[1]:=oo;mi[n+2]:=oo;a[1]:=oo;a[n+2]:=oo;<br /> n:=n+2;<br />end;<br />procedure update(i:longint);<br />begin<br /> son[i]:=son[l[i]]+son[r[i]]+1;<br /> mi[i]:=min(min(mi[l[i]],mi[r[i]]),a[i]);<br />end;<br />procedure left(var i:longint);<br />var j:longint;<br />begin<br /> j:=r[i];r[i]:=l[j];l[j]:=i;<br /> update(i);update(j);<br /> i:=j;<br />end;<br />procedure right(var i:longint);<br />var j:longint;<br />begin<br /> j:=l[i];l[i]:=r[j];r[j]:=i;<br /> update(i);update(j);<br /> i:=j;<br />end;<br />procedure put1(i,j:longint);<br />begin<br /> if i=0 then exit;<br /> a[i]:=a[i]+j;mi[i]:=mi[i]+j;<br /> b1[i]:=b1[i]+j;<br />end;<br />procedure put2(i:longint);<br />var z:longint;<br />begin<br /> if i=0 then exit;<br /> z:=l[i];l[i]:=r[i];r[i]:=z;<br /> b2[i]:=1-b2[i];<br />end;<br />procedure up(var i:longint;k:longint);<br />begin<br /> if i=0 then exit;<br /> if b1[i]>0 then begin<br /> put1(l[i],b1[i]);put1(r[i],b1[i]);<br /> b1[i]:=0;<br /> end;<br /> if b2[i]>0 then begin<br /> put2(l[i]);put2(r[i]);<br /> b2[i]:=0;<br /> end;<br /> if k<=son[l[i]] then begin<br /> up(l[i],k);right(i);<br /> end<br /> else<br /> if k>son[l[i]]+1 then begin<br /> up(r[i],k-son[l[i]]-1);left(i);<br /> end;<br />end;<br />procedure work;<br />var i,j,k,kk,c,z:longint;<br /> st:string;<br />begin<br /> readln(task);<br /> for task:=1 to task do begin<br /> readln(st);<br /> while st[length(st)]=' ' do delete(st,length(st),1);st:=st+' ';<br /> if (st[1]='A') then c:=1 else<br /> if (st[1]='R')and(st[4]='E') then c:=2 else<br /> if (st[1]='R')and(st[4]='O') then c:=3 else<br /> if (st[1]='I') then c:=4 else<br /> if (st[1]='D') then c:=5 else c:=6;<br /> delete(st,1,pos(' ',st));<br /> val(copy(st,1,pos(' ',st)-1),i,z);<br /> delete(st,1,pos(' ',st));<br /> if length(st)>1 then begin<br /> val(copy(st,1,pos(' ',st)-1),j,z);<br /> delete(st,1,pos(' ',st));<br /> if length(st)>1 then val(copy(st,1,length(st)-1),k,z);<br /> end;<br /> case c of<br /> 1:begin<br /> inc(i);inc(j);<br /> up(root,i-1);up(root,j+1);<br /> put1(r[l[root]],k);<br /> end;<br /> 2:begin<br /> inc(i);inc(j);<br /> up(root,i-1);up(root,j+1);<br /> put2(r[l[root]]);<br /> end;<br /> 3:begin<br /> inc(i);inc(j);<br /> up(root,i-1);up(root,j+1);k:=k mod (j-i+1);<br /> if k>0 then begin<br /> kk:=r[l[root]];<br /> up(kk,j-k-i+1);<br /> up(r[kk],k);<br /> z:=r[kk];r[z]:=kk;r[l[root]]:=z;r[kk]:=0;<br /> update(r[z]);update(z);<br /> end;<br /> end;<br /> 4:begin<br /> inc(i);<br /> inc(n);a[n]:=j;mi[n]:=j;j:=n;<br /> up(root,i);r[j]:=r[root];r[root]:=j;<br /> update(j);update(root);<br /> end;<br /> 5:begin<br /> inc(i);<br /> up(root,i);<br /> up(r[root],1);<br /> l[r[root]]:=l[root];root:=r[root];<br /> update(root);<br /> end;<br /> 6:begin<br /> inc(i);inc(j);<br /> up(root,i-1);up(root,j+1);<br /> writeln(mi[r[l[root]]]);<br /> end;<br /> end;<br /> end;<br />end;<br />begin<br /> assign(input,'pku3580.in');reset(input);<br /> assign(output,'pku3580.out');rewrite(output);<br /> init;<br /> work;<br /> close(input);<br /> close(output);<br />end.<br />

 

一題一結構,無題不演算法

 

 

     

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.