codeforces 38G - Queue splay伸展树

Posted nervendnig

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 38G - Queue splay伸展树相关的知识,希望对你有一定的参考价值。

题目

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

题意:

一些人按顺序进入队列,每个人有两个属性,地位$A$和能力$C$

每个人进入时都在队尾,并最多可以和前一位互换$C$次,如果前一位的地位高于自己,则无法继续互换.

最终一次性输出整个队列

题解:

splay维护动态的队列

可以用类似权值线段树的思维去考虑

对于每个点,保存其子节点的最大值,自身的值,与子树的大小

对于每次插入时,若能跨过整颗右子树与当前节点,则向左走,否则向右

可以保证整个子树中序遍历的顺序即为当前队列

又因为是平衡树,每次插入一个点,都将该点旋转至根,因此均摊复杂度$O(logn)$

技术分享图片

#include <bits/stdc++.h>
#define endl ‘
‘
#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;
}

 

以上是关于codeforces 38G - Queue splay伸展树的主要内容,如果未能解决你的问题,请参考以下文章

codeforces 686B B. Little Robber Girl's Zoo(水题)

CodeForces545D Queue

Codeforce 545D. Queue

Codeforces 545D - Queue

CodeForces 767B The Queue

Queue CodeForces - 353D (思维dp)