【序列之神splay】poj3580

來源:互聯網
上載者:User

首先藉助Google大叔吧這道題看懂了。

和【noi維護數列】比較相像,可以說是其簡化版本,需要維護的東西少一點,操作要多一個。

簡要的來說,他是要支援者樣幾種操作:

     1.插入刪除;

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

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

     4.一段全部增加k;

     5.詢問一段的最小值。

前一段時間學習了一下Splay,亮點就在與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]:

             這個操作稍微麻煩一點,先把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。

      

 

Splay一共5種旋轉,寫起來稍麻煩,特判比較多,程式一下子就醜了起來,於是抱著僥倖的心理,編寫了只有左旋右旋兩種旋轉的‘Splay’(酷似treap);編起來非常舒服,最後111行寫完了,交程式的時候,AC的字樣著實讓我興奮了下,下面是記錄:

Run ID User Problem Result Memory Time Language Code Length Submit Time
7196764 cjLD 3580 Accepted 5016K 1266MS Pascal 2689B 2010-07-19 22:13:35

 

速度是慢了點,這你別怪我,但是2689B的長度到是非常可觀,真真考試的時候還是要考慮下編程複雜度的。

關於專門卡的資料也不怕,只要在每次操作後random一個數提根,還是很有效。

 

貼代碼:

 

 

program poj3580; const maxlongint=maxlongint>>1;<br />var<br /> l,r,m,ad,w,s:array[0..200010] of longint;<br /> f:array[0..200010] of boolean;<br /> i,j,ll,rr,t,tmp,root,n,mt,a,b,c,d:longint;<br /> task:string;<br /> rd:char;</p><p>procedure update(i:longint);<br />begin<br /> if i=0 then exit;<br /> ll:=l[i];rr:=r[i];<br /> s[i]:=s[ll]+s[rr]+1;<br /> m[i]:=w[i];<br /> if m[ll]<m[i] then m[i]:=m[ll];<br /> if m[rr]<m[i] then m[i]:=m[rr];<br />end;</p><p>procedure left(var i:longint);<br />begin<br /> j:=r[i];r[i]:=l[j];l[j]:=i;<br /> update(i);update(j);<br /> i:=j;<br />end;</p><p>procedure right(var i:longint);<br />begin<br /> j:=l[i];l[i]:=r[j];r[j]:=i;<br /> update(i);update(j);<br /> i:=j;<br />end;</p><p>procedure put(var i,j:longint;k:boolean);<br />begin<br /> if i=0 then exit;<br /> if k then begin<br /> tmp:=l[i];l[i]:=r[i];r[i]:=tmp;<br /> end;<br /> f[i]:=f[i] xor k;<br /> inc(w[i],j);inc(ad[i],j);inc(m[i],j);//!<br />end;</p><p>procedure find(var i:longint;p:longint);<br />begin<br /> put(l[i],ad[i],f[i]);<br /> put(r[i],ad[i],f[i]);<br /> ad[i]:=0;f[i]:=false; //!<br /> if p<=s[l[i]] then begin<br /> find(l[i],p); right(i);<br /> end else<br /> if p=s[l[i]]+1 then exit else begin<br /> find(r[i],p-s[l[i]]-1); left(i);<br /> end;<br />end;</p><p>begin<br /> readln(n);<br /> t:=n; m[0]:=maxlongint;<br /> root:=n+2; t:=root;//!<br /> i:=1; w[1]:=maxlongint; update(i);<br /> for i:=2 to n+1 do begin<br /> readln(w[i]);<br /> l[i]:=i-1;update(i);<br /> end;<br /> w[root]:=maxlongint; l[root]:=i; update(root);<br /> readln(mt);<br /> for mt:=1 to mt do begin<br /> task:='';rd:='!';<br /> while rd<>' ' do begin<br /> task:=task+rd;read(rd);<br /> end;<br /> if task='!ADD' then begin<br /> readln(a,b,c); b:=b+2;<br /> find(root,a);find(root,b);<br /> put(r[l[root]],c,false);<br /> update(l[root]);update(root);<br /> end else<br /> if task='!REVERSE' then begin<br /> readln(a,b); b:=b+2; c:=0;<br /> find(root,a);find(root,b);<br /> put(r[l[root]],c,true);<br /> end else<br /> if task='!REVOLVE' then begin<br /> readln(a,b,c);<br /> while c<0 do c:=c+b-a+1;<br /> c:=b-c mod (b-a+1)+1; b:=b+2;<br /> find(root,c);find(l[root],a);<br /> find(r[root],b-c);<br /> a:=r[l[root]];b:=l[r[root]]; c:=l[root];<br /> r[c]:=b; l[root]:=a; l[r[root]]:=0;<br /> update(c);update(r[root]);update(root);<br /> find(root,1);<br /> l[root]:=c; update(root);<br /> end else<br /> if task='!INSERT' then begin<br /> readln(a,b);find(root,a+1);//!<br /> inc(t);r[t]:=r[root];r[root]:=t;w[t]:=b;<br /> update(t);update(root);<br /> end else<br /> if task='!DELETE' then begin<br /> readln(a);inc(a);<br /> find(root,a);find(r[root],1);<br /> l[r[root]]:=l[root];root:=r[root];<br /> update(root);<br /> end else begin<br /> readln(a,b);b:=b+2;<br /> find(root,a);find(root,b);<br /> writeln(m[r[l[root]]]);<br /> end;<br /> end;<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.