分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap。
画一画图就可以解决这道题了,自己试一下。
代码如下:
#include<bits/stdc++.h> using namespace std; const int maxn = 102000; int m,xxx; namespace Treap{ struct spaly{int son[2],fa;}t[maxn]; int sz[maxn],ch[maxn][2],num,SpalyRoot,Prs[maxn]; int key[maxn],lazy[maxn],dep[maxn],data[maxn],root; void push_down(int now){ dep[now] += lazy[now]; lazy[ch[now][0]] += lazy[now]; lazy[ch[now][1]] += lazy[now]; lazy[now] = 0; } int merge(int root1,int root2){ if(!root1) return root2; if(!root2) return root1; if(lazy[root1]) push_down(root1); if(lazy[root2]) push_down(root2); if(key[root1] <= key[root2]){ ch[root1][1] = merge(ch[root1][1],root2); Prs[ch[root1][1]] = root1; sz[root1] = sz[ch[root1][0]] + sz[ch[root1][1]] + 1; return root1; }else{ ch[root2][0] = merge(root1,ch[root2][0]); Prs[ch[root2][0]] = root2; sz[root2] = sz[ch[root2][0]] + sz[ch[root2][1]] + 1; return root2; } } pair<int,int> split(int Node,int Len){ if(Len == 0) return make_pair(0,Node); if(Node == 0) return make_pair(0,0); if(lazy[Node]) push_down(Node); if(sz[ch[Node][0]] >= Len){ pair<int,int> Ans = split(ch[Node][0],Len); ch[Node][0] = Ans.second; Prs[Ans.second] = Node; Ans.second = Node; Prs[Ans.first] = 0; sz[Node] = sz[ch[Node][0]] + sz[ch[Node][1]] + 1; return Ans; }else{ pair<int,int> Ans = split(ch[Node][1],Len-sz[ch[Node][0]]-1); ch[Node][1] = Ans.first; Prs[Ans.first] = Node; Ans.first = Node; Prs[Ans.second] = 0; sz[Node] = sz[ch[Node][0]] + sz[ch[Node][1]] + 1; return Ans; } } int get_rank(int Node,int Val){ if(Node == 0) return 0; if(data[Node] > Val) return get_rank(ch[Node][0],Val); else return sz[ch[Node][0]]+1+get_rank(ch[Node][1],Val); } int get_Kth(int Node){ stack<int> sta; int pts = Node; while(pts){sta.push(pts),pts = Prs[pts];} int Th = 0; while(!sta.empty()){ int dat = sta.top();sta.pop(); if(lazy[dat]) push_down(dat); if(!sta.empty()&&ch[dat][1] == sta.top()){ Th += sz[ch[dat][0]] + 1; } } Th += sz[ch[Node][0]] + 1; return Th; } } namespace operation{ using namespace Treap; int Insert(int Val){ if(root == 0){ root++;sz[root]=1;key[root]=rand();data[root]=Val;dep[root]=1; num++;SpalyRoot++;return dep[root]; } num++;sz[num] = 1;key[num] = rand();data[num] = Val; int rk = get_rank(root,Val); pair<int,int> nowp = split(root,rk); int rt = nowp.first,lt = nowp.second; while(ch[rt][1]) {if(lazy[rt])push_down(rt); rt = ch[rt][1];} while(ch[lt][0]) {if(lazy[lt])push_down(lt); lt = ch[lt][0];} if(lazy[rt]&&rt) push_down(rt); if(lazy[lt]&<) push_down(lt); if(!t[rt].son[1] && rt != 0){ t[rt].son[1] = num;t[num].fa = rt;dep[num] = dep[rt]+1; }else{ t[lt].son[0] = num;t[num].fa = lt;dep[num] = dep[lt]+1; } root = merge(merge(nowp.first,num),nowp.second); return dep[num]; } int Spaly(int Kind){ // 0 min,1 max int nowp = root; while(ch[nowp][Kind]){ if(lazy[nowp])push_down(nowp); nowp=ch[nowp][Kind]; } if(nowp == SpalyRoot){return 1;} int Son = t[nowp].son[Kind^1],Father = t[nowp].fa; t[nowp].son[Kind^1] = SpalyRoot; t[SpalyRoot].fa = nowp; SpalyRoot = nowp;t[nowp].fa = 0;int finalans; int Len = get_Kth(Father); t[Father].son[Kind] = Son; t[Son].fa = Father; if(Kind == 0){ pair<int,int> Ans = split(root,Len-1); pair<int,int> Cut = split(Ans.first,1); lazy[Ans.second]++; if(lazy[Cut.first]) push_down(Cut.first); finalans = dep[nowp]; dep[Cut.first] = 1; root = merge(merge(Cut.first,Cut.second),Ans.second); }else{ pair<int,int> Ans = split(root,Len); pair<int,int> Cut = split(Ans.second,sz[Ans.second]-1); lazy[Ans.first]++; if(lazy[Cut.second]) push_down(Cut.second); finalans = dep[nowp];dep[Cut.second] = 1; root = merge(Ans.first,merge(Cut.first,Cut.second)); } return finalans; } int Erase(int Kind){//0 min 1 max int finalans = Spaly(Kind); int nowp = root; while(ch[nowp][Kind]){ if(lazy[nowp])push_down(nowp); nowp=ch[nowp][Kind]; } SpalyRoot = t[nowp].son[Kind^1]; t[SpalyRoot].fa = 0;t[nowp].son[Kind^1] = 0; pair<int,int> Les = split(root,get_Kth(nowp)); pair<int,int> Spt = split(Les.first,get_Kth(nowp)-1); root = merge(Spt.first,Les.second); if(root != 0) lazy[root]--; return finalans; } } void work(){ for(int i=1;i<=m;i++){xxx=i; int opt,x; scanf("%d",&opt); if(opt == 2 || opt == 3) printf("%d\n",operation::Spaly(opt%2)); else if(opt == 4 || opt == 5) printf("%d\n",operation::Erase(opt%2)); else {scanf("%d",&x);printf("%d\n",operation::Insert(x));} } } int main(){ srand(19260817); scanf("%d",&m); work(); return 0; }