1. 程式人生 > >codeforces 38G - Queue splay伸展樹

codeforces 38G - Queue splay伸展樹

題目

https://codeforces.com/problemset/problem/38/G

題意:

一些人按順序進入佇列,每個人有兩個屬性,地位$A$和能力$C$

每個人進入時都在隊尾,並最多可以和前一位互換$C$次,如果前一位的地位高於自己,則無法繼續互換.

最終一次性輸出整個佇列

題解:

splay維護動態的佇列

可以用類似權值線段樹的思維去考慮

對於每個點,儲存其子節點的最大值,自身的值,與子樹的大小

對於每次插入時,若能跨過整顆右子樹與當前節點,則向左走,否則向右

可以保證整個子樹中序遍歷的順序即為當前佇列

又因為是平衡樹,每次插入一個點,都將該點旋轉至根,因此均攤複雜度$O(logn)$

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
class splaytree{
#define nd node[now]
#define ndl	node[node[now].son[0]]
#define ndr node[node[now].son[1]]
	public:
  struct splaynode{
    int son[2],pre;
    int val,mx,size;
    splaynode(){mx=val=size=pre=son[0]=son[1]=0;}
    splaynode(int x,int fa=0){mx=val=x;pre=fa;son[0]=son[1]=0;size=1;}
  };
  int cnt,root;
  vector<splaynode> node;
	void pushup(int now){
		nd.mx=nd.val,nd.size=1;
		rep(i,0,1)if(nd.son[i]) {
			nd.mx=max(node[nd.son[i]].mx,nd.mx);
			nd.size+=node[nd.son[i]].size;
		}
	}
	void pushdown(int now){}
	void rotate(int now,int d){
    int fa=nd.pre;
    pushdown(fa);pushdown(now);
    node[fa].son[!d]=nd.son[d];
    node[nd.son[d]].pre=fa;
    if(node[fa].pre){
			node[node[fa].pre].son[node[node[fa].pre].son[1]==fa]=now;
    }else root=now;
    nd.pre=node[fa].pre;
    nd.son[d]=fa,node[fa].pre=now;
    pushup(fa);pushup(now);
  }
  void splay(int now,int dst){
  	pushdown(now);
    while(nd.pre!=dst){
      if(node[nd.pre].pre==dst)rotate(now,node[nd.pre].son[0]==now);
      else{
	    	int fa=nd.pre,d=(node[node[fa].pre].son[0]==fa);
		    if(node[fa].son[d]==now){rotate(now,!d);rotate(now,d);}
				else {rotate(fa,d);rotate(now,d);}
			}
    }
    if(!dst) root=now;
    pushup(now);
  }
  void insert(int val,int len){
  	if(!root){
			node[++cnt]=splaynode(val);
			root=cnt;
			return;
  	}
  	int now=root;
  	int flag=(val<(max(nd.val,ndr.mx))||len<ndr.size+1);
		while(1){
			if(!nd.son[flag]){
				node[++cnt]=splaynode(val,now);
				nd.son[flag]=cnt;
				break;
			}
			if(!flag)len-=ndr.size+1;
			now=nd.son[flag];
			flag=(val<(max(nd.val,ndr.mx))||len<ndr.size+1);
		}
		pushup(now);
		splay(cnt,0);
  }
  void print(){print(root);}
  void print(int now){
		if(nd.son[0]) print(nd.son[0]);
		cout<<now<<' ';
		if(nd.son[1]) print(nd.son[1]);
  }
  splaytree(int n){
    node.resize(n+7);
    root=0,cnt=0;
  }
};
int main() {
	IO;
	cin>>n;
	splaytree tree(n);
	rep(i,1,n){
		int a,b;cin>>a>>b;
		tree.insert(a,b);
	}
	tree.print();
	return 0;
}