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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[SCOI2014]方伯伯的OJ

發(fā)布時(shí)間:2024/6/30 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [SCOI2014]方伯伯的OJ 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

看到這道題的第一想法就是要用FHQ treap 過(guò)了這道題...于是至今尚未成功(華麗的 T 掉了 (╯‵□′)╯︵┻━┻ )。于是附個(gè)地址。

然后水一波博客。

?

題意簡(jiǎn)介

emmmm...方伯伯腦抽做了個(gè) oj ,然后想要在對(duì) oj 上的 1~n 編號(hào)的用戶亂來(lái)(并且還對(duì)他的亂來(lái)操作進(jìn)行了加密)。你需要維護(hù)一棵平衡樹(shù)完成方伯伯的一波操作

你的平衡樹(shù)需要支持這些操作: 1. 修改編號(hào); 2. 把一個(gè)人放到樹(shù)的最左邊; 3. 把一個(gè)人放到樹(shù)的最右邊;4.輸出一個(gè)排名對(duì)應(yīng)的編號(hào)。

?

題目分析

然后這道題非常坑,要用 map 記錄每個(gè)節(jié)點(diǎn)對(duì)應(yīng)區(qū)間右端點(diǎn)的對(duì)應(yīng)節(jié)點(diǎn)編號(hào) (聽(tīng)起來(lái)很繞,其實(shí)就是: 設(shè)某節(jié)點(diǎn)對(duì)應(yīng)區(qū)間右端點(diǎn)為 R , 該節(jié)點(diǎn)編號(hào)為 p , 那么我們用的map 的 first key 就是 R ,second key 是 p),然后用找某個(gè)編號(hào)所在的節(jié)點(diǎn)用 lower_bound 就好了(才知道m(xù)ap是可以 lower bound 的,并且是以第一關(guān)鍵字作比較的)。我記得有看到用另一種利用 map 的方法,那好像是 普通 treap (splay應(yīng)該也能用啊)的,而且節(jié)點(diǎn)維護(hù)的區(qū)間也有點(diǎn)混亂...就是這個(gè)

?

Splay 做法

1 //by Judge2 #include<iostream>3 #include<cstdio>4 #include<map>5 using namespace std;6 const int M=5e5+111;7 //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)8 char buf[1<<21],*p1=buf,*p2=buf;9 inline int read(){10 int x=0,f=1; char c=getchar();11 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; 12 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; 13 } 14 char sr[1<<21],z[20];int C=-1,Z; 15 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 16 inline void print(int x){ 17 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 18 while(z[++Z]=x%10+48,x/=10); 19 while(sr[++C]=z[Z],--Z);sr[++C]='\n'; 20 } 21 int n,m,cnt,ans,root; 22 map<int,int> mp; 23 struct Node{ 24 int l,r,siz,fa,ch[2]; 25 }t[M]; 26 inline int newnode(int x,int y){ int u=++cnt; t[u].siz=y-x+1,t[u].l=x,t[u].r=y; return u; } 27 inline void pushup(int x){ t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+t[x].r-t[x].l+1; } 28 inline void rotate(int x){ 29 int y=t[x].fa,z=t[y].fa,sn=t[y].ch[1]==x; 30 t[x].fa=z; if(z) t[z].ch[t[z].ch[1]==y]=x; 31 t[y].ch[sn]=t[x].ch[!sn],t[t[y].ch[sn]].fa=y; 32 t[y].fa=x,t[x].ch[!sn]=y,pushup(y); 33 } 34 inline void splay(int x,int to){ 35 while(t[x].fa^to){ 36 int y=t[x].fa,z=t[y].fa; 37 if(z!=to) rotate((t[z].ch[0]==y)^(t[y].ch[0]==x)?x:y); 38 rotate(x); 39 } pushup(x); if(!to) root=x; 40 } 41 inline int query(int x){ splay(x,0); return t[x].siz-t[t[x].ch[1]].siz; } 42 inline int get_id(int k){ //查詢排名為 k 的人的編號(hào) 43 int now=root; 44 while(k){ 45 int sum=t[t[now].ch[0]].siz+t[now].r-t[now].l+1; 46 if(t[t[now].ch[0]].siz<k && k<=sum){ 47 k-=t[t[now].ch[0]].siz; break; 48 } else if(sum<k) k-=sum,now=t[now].ch[1]; 49 else now=t[now].ch[0]; 50 } return t[now].l+k-1; 51 } 52 inline void erase(int x){ //刪除節(jié)點(diǎn)信息 53 int pre=t[x].ch[0],nxt=t[x].ch[1]; 54 while(t[pre].ch[1]) pre=t[pre].ch[1]; 55 while(t[nxt].ch[0]) nxt=t[nxt].ch[0]; 56 if(!pre && !nxt) return (void)(root=0); 57 if(!pre) splay(nxt,root),t[root=nxt].fa=0; 58 else if(!nxt) splay(pre,root),t[root=pre].fa=0; 59 else splay(pre,0),splay(nxt,pre),t[nxt].ch[0]=0,pushup(nxt),pushup(pre); 60 t[x].ch[0]=t[x].ch[1]=0,t[x].siz=1; //不知道為什么這里不寫(xiě)會(huì) T (懶得想咯應(yīng)該是編號(hào)改完可能會(huì)改回來(lái)的問(wèn)題吧) 61 } 62 inline void push_front(int x){ //插頭 63 if(!root) return (void)(root=x); int fa=root; 64 while(t[fa].ch[0]) ++t[fa].siz,fa=t[fa].ch[0]; 65 ++t[fa].siz,t[fa].ch[0]=x,t[x].fa=fa,splay(x,0); 66 } 67 inline void push_back(int x){ //插尾 68 if(!root) return (void)(root=x); int fa=root; 69 while(t[fa].ch[1]) ++t[fa].siz,fa=t[fa].ch[1]; 70 ++t[fa].siz,t[fa].ch[1]=x,t[x].fa=fa,splay(x,0); 71 } 72 inline void split(int x,int id){ //拆出節(jié)點(diǎn) 73 int L=t[x].l,R=t[x].r,ls,rs; 74 if(L==R) return ; //不用拆 75 if(L==id){ //最左端 76 mp[R]=rs=++cnt,mp[id]=x; 77 t[rs].ch[1]=t[x].ch[1]; 78 t[t[rs].ch[1]].fa=rs; 79 t[x].ch[1]=rs,t[rs].fa=x; 80 t[rs].l=L+1,t[rs].r=R,t[x].r=L; 81 pushup(rs),pushup(x); 82 } else if(R==id){ //最右端 83 mp[R-1]=ls=++cnt,mp[id]=x; 84 t[ls].ch[0]=t[x].ch[0]; 85 t[t[ls].ch[0]].fa=ls; 86 t[x].ch[0]=ls,t[ls].fa=x; 87 t[ls].l=L,t[ls].r=R-1,t[x].l=R; 88 pushup(ls),pushup(x); 89 } else{ //在中間 90 mp[id]=x,mp[id-1]=ls=++cnt,mp[R]=rs=++cnt; 91 t[ls].ch[0]=t[x].ch[0],t[rs].ch[1]=t[x].ch[1]; 92 t[t[ls].ch[0]].fa=ls,t[t[rs].ch[1]].fa=rs; 93 t[x].ch[0]=ls,t[x].ch[1]=rs,t[ls].fa=t[rs].fa=x; 94 t[x].l=t[x].r=id,t[ls].l=L,t[ls].r=id-1,t[rs].l=id+1,t[rs].r=R; 95 pushup(ls),pushup(rs),pushup(x); 96 } 97 } 98 signed main() { 99 n=read(),m=read(), 100 mp[n]=root=newnode(1,n); 101 for(int x,y,pos,opt;m;--m){ 102 opt=read(); 103 switch(opt){ 104 case 1: 105 x=read()-ans,y=read()-ans; 106 pos=mp.lower_bound(x)->second; //map 里面找節(jié)點(diǎn)編號(hào) 107 split(pos,x),ans=query(pos); //拆出節(jié)點(diǎn)查排名 108 t[pos].l=t[pos].r=y,mp[y]=pos; //修改信息輸答案 109 print(ans); break; 110 case 2: 111 x=read()-ans, pos=mp.lower_bound(x)->second; 112 split(pos,x),ans=query(pos),erase(pos); //拆除節(jié)點(diǎn)再刪除 113 push_front(pos),print(ans); break; //節(jié)點(diǎn)重新加入樹(shù) 114 case 3: 115 x=read()-ans, pos=mp.lower_bound(x)->second; 116 split(pos,x),ans=query(pos),erase(pos); 117 push_back(pos),print(ans); break; 118 case 4: 119 x=read()-ans,ans=get_id(x),print(ans); break; //詢問(wèn)編號(hào)直輸出 120 } 121 } Ot(); return 0; 122 }

?

FHQ treap

?

轉(zhuǎn)載于:https://www.cnblogs.com/Judge/p/9538306.html

總結(jié)

以上是生活随笔為你收集整理的[SCOI2014]方伯伯的OJ的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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