HYSBZ - 1503 郁闷的出纳员(Splay)
生活随笔
收集整理的這篇文章主要介紹了
HYSBZ - 1503 郁闷的出纳员(Splay)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:中文題
題目分析:利用Splay加一點思維還是比較容易解決的,對于所有員工加工資以及減工資的操作,別看只有100次,如果是暴力修改的話,時間復雜度能達到1e7,常數稍大點的模板可能就頂不住了,這里可以思考一下,我們在伸展樹中儲存的可以是每個員工的相對工資,對于老員工加工資,相對于新員工來說就是減工資了,反之同理,所以我們可以維護一個diff變量,用來記錄老員工工資的變動情況,這樣對于每個新加入的員工來說,其相對工資就變成了 x - diff 了,其中有個詢問第 k 大的員工的工資時,從伸展樹中取出數據后別忘了加上 diff 變量恢復到絕對大小,因為在伸展樹中保存的是每個員工的相對大小,這樣每個操作相對就比較簡單了
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;int ans=0;class Splay {public:int ch[N][2],f[N],size[N],cnt[N],key[N];//size:子樹大小,cnt:當前節點出現次數,key:權值 int sz,root;inline void clear(int x){ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;}inline bool get(int x){return ch[f[x]][1]==x;}inline void update(int x){if(x){size[x]=cnt[x];if(ch[x][0]) size[x]+=size[ch[x][0]];if(ch[x][1]) size[x]+=size[ch[x][1]];}}inline void rotate(int x){int old=f[x],oldf=f[old],whichx=get(x);ch[old][whichx]=ch[x][whichx^1]; f[ch[old][whichx]]=old;ch[x][whichx^1]=old; f[old]=x;f[x]=oldf;if(oldf)ch[oldf][ch[oldf][1]==old]=x;update(old); update(x);}inline void splay(int x){for(int fa;fa=f[x];rotate(x))if(f[fa])rotate((get(x)==get(fa))?fa:x);root=x;}inline void insert(int x){if(root==0){sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; root=sz; size[sz]=cnt[sz]=1; key[sz]=x; return;}int now=root,fa=0;while(1){if(x==key[now]){cnt[now]++; update(now); update(fa); splay(now); break;}fa=now;now=ch[now][key[now]<x];if(now==0){sz++;ch[sz][0]=ch[sz][1]=0;f[sz]=fa;size[sz]=cnt[sz]=1;ch[fa][key[fa]<x]=sz;key[sz]=x;update(fa);splay(sz);break;}}}inline int find(int x)//查詢x的排名{int now=root,ans=0;while(1){if(x<key[now])now=ch[now][0];else{ans+=(ch[now][0]?size[ch[now][0]]:0);if(x==key[now]){splay(now); return ans+1;}ans+=cnt[now];now=ch[now][1];}}}inline int findx(int x)//找到排名為x的點{int now=root;while(1){if(ch[now][0]&&x<=size[ch[now][0]])now=ch[now][0];else{int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];if(x<=temp) return key[now];x-=temp; now=ch[now][1];}}}inline int pre()//小于某個數的最大值 {int now=ch[root][0];while(ch[now][1]) now=ch[now][1];return now;}inline int next()//大于某個數的最小值 {int now=ch[root][1];while(ch[now][0]) now=ch[now][0];return now;}inline void del(int x){int whatever=find(x);if(cnt[root]>1){cnt[root]--; update(root); return;}if(!ch[root][0]&&!ch[root][1]) {clear(root); root=0; return;}if(!ch[root][0]){int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); return;}else if(!ch[root][1]){int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); return;}int leftbig=pre(),oldroot=root;splay(leftbig);ch[root][1]=ch[oldroot][1];f[ch[oldroot][1]]=root;clear(oldroot);update(root); }inline void pop(int x){insert(x);ans+=size[ch[root][0]];size[root]-=size[ch[root][0]];ch[root][0]=0;del(x);} }tree;int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,diff=0;scanf("%d%d",&n,&m);while(n--){char s[5];int x;scanf("%s%d",s,&x);if(s[0]=='I'){if(x>=m)tree.insert(x-diff);}else if(s[0]=='A'){diff+=x;}else if(s[0]=='S'){diff-=x;tree.pop(m-diff);}else if(s[0]=='F'){int all=tree.size[tree.root];if(x>all)printf("%d\n",-1);elseprintf("%d\n",tree.findx(all+1-x)+diff);}}printf("%d\n",ans);return 0; }?
總結
以上是生活随笔為你收集整理的HYSBZ - 1503 郁闷的出纳员(Splay)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HYSBZ - 1588 营业额统计(S
- 下一篇: CodeForces - 1316B S