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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

●HDU 2871 Memory Control(Splay)

發布時間:2024/4/17 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ●HDU 2871 Memory Control(Splay) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

●贅述題目

四種操作:

○Reset:將整個內存序列清空

○New a:在盡量靠左的位置新建一個長度為a的內存塊,并輸出改內存塊起始位置。(各個內存塊即使相鄰也不會合并。。)

○Free a:將a點所在的內存塊清空,并輸出清空的內存區間的左右端點。

○Get a:輸出從左往右數的第a個內存塊的起始位置。

●題解

方法:Splay在線維護

(○本來想的將序列中的每個點看作Splay樹中的一個節點,然后進行區間操作。。但似乎比較麻煩。。)

○正解(erge大佬提出的思路):考慮到每個內存塊不會合并的性質,將每一個內存塊看作Splay樹中的一個節點,且中序遍歷各個節點的順序即對應內存序列中各個內存塊的從左至右的順序(如下圖)(區間化點)。然后剩下便是Splay的單點操作。

○為方便一些操作,先就加入兩個邊界點。

?

●代碼

(注意NEW(insert)函數啊,有點坑坑。。)

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 50005 #define ls tr[k][0] #define rs tr[k][1] using namespace std; int fa[MAXN],tr[MAXN][2]; int l[MAXN],r[MAXN],ll[MAXN],rr[MAXN],ma[MAXN],siz[MAXN]; int tot,root; void pushup(int k) {ll[k]=ls?ll[ls]:l[k]; rr[k]=rs?rr[rs]:r[k];ma[k]=max(max(ls?ma[ls]:0,rs?ma[rs]:0),max(ls?l[k]-rr[ls]-1:0,rs?ll[rs]-r[k]-1:0));siz[k]=1+(ls?siz[ls]:0)+(rs?siz[rs]:0); } void rotate(int x,int &k) {int y=fa[x],z=fa[y];int l=tr[y][1]==x,r=1^l;if(y==k) k=x;else tr[z][tr[z][1]==y]=x;fa[tr[x][r]]=y; fa[y]=x; fa[x]=z;tr[y][l]=tr[x][r]; tr[x][r]=y;pushup(y); } void splay(int x,int &k) {int y,z;while(x!=k){y=fa[x]; z=fa[y];if(y!=k) ((tr[z][0]==y)^(tr[y][0]==x)) ? rotate(x,k):rotate(y,k);rotate(x,k);}pushup(x); } int NEW(int &k,int last,int len,int fg,int sl) {if(!k){k=++tot;fa[k]=last;l[k]=sl; r[k]=l[k]+len-1;tr[k][0]=tr[k][1]=0;splay(k,root);return l[root];} if(fg==0) return NEW(rs,k,len,0,r[k]+1);else if(fg==1) return NEW(ls,k,len,1,sl);else if(ls&&ma[ls]>=len) return NEW(ls,k,len,-1,sl);else if(ls&&l[k]-rr[ls]-1>=len) return NEW(ls,k,len,0,r[k]+1);else if(rs&&ll[rs]-r[k]-1>=len) return NEW(rs,k,len,1,r[k]+1);else if(rs&&ma[rs]>=len) return NEW(rs,k,len,-1,sl);return 0; } int find(int k,int x) {if(ll[ls]<=x&&x<=rr[ls]) return find(ls,x);else if(l[k]<=x&&x<=r[k]) return k;else if(ll[rs]<=x&&x<=rr[rs]) return find(rs,x);return 0; } int FREE(int x) {int k=find(root,x);if(!k) return 0;splay(k,root);if(ls*rs==0) root=ls+rs,fa[root]=0;else{int p=rs;while(tr[p][0]) p=tr[p][0];tr[p][0]=ls;fa[ls]=p;root=rs;fa[root]=0;splay(ls,root);}return k; } int GET(int k,int x) {if(siz[ls]>=x) return GET(ls,x); x-=siz[ls];if(x==1) return l[k]; x-=1;if(siz[rs]>=x) return GET(rs,x);return 0; } void pre(int n) {root=1; tot=2;tr[1][0]=0; tr[1][1]=2; tr[2][0]=0; tr[2][1]=0;fa[2]=1;l[1]=r[1]=0; l[2]=r[2]=n+1;pushup(2); pushup(1); } int main() {int n,m,a,b; char s[10]; while(~scanf("%d%d",&n,&m)){pre(n);while(m--){scanf(" %s",s);if(s[0]=='R') pre(n),printf("Reset Now\n");else if(s[0]=='N') scanf("%d",&a),1<=a&&a<=n?b=NEW(root,0,a,-1,-1):b=0,b?printf("New at %d\n",b):printf("Reject New\n");else if(s[0]=='F') scanf("%d",&a),1<=a&&a<=n?b=FREE(a):b=0,b?printf("Free from %d to %d\n",l[b],r[b]):printf("Reject Free\n");else if(s[0]=='G') scanf("%d",&a),siz[root]-2>=a?b=GET(root,a+1):b=0,b?printf("Get at %d\n",b):printf("Reject Get\n"); }printf("\n");}return 0; }

轉載于:https://www.cnblogs.com/zj75211/p/7251160.html

總結

以上是生活随笔為你收集整理的●HDU 2871 Memory Control(Splay)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。