社区讨论

带旋Treap(三棵平衡树)MLE 70pts MnZn 求助

P1110[ZJOI2007] 报表统计参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lyqq41yc
此快照首次捕获于
2024/07/18 11:40
2 年前
此快照最后确认于
2024/07/18 13:18
2 年前
查看原帖
C
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+10,md = 1e7+7;
#define int long long 
//维护三棵差值平衡树,一棵平衡树维护的是两个相邻的数的差,一棵平衡树维护的是排序后的数,一棵平衡树维护的是排序后的数的差
int n,m,a[N],rt,rt2,cnt,cnt2,rt3,cnt3,b[N]; 
struct T{
	int l;
	int r;
	int val;
	int pri;
	int size;
}tree[N],tree2[N],tree3[N];
void update(int x){
	tree[x].size=tree[tree[x].l].size+tree[tree[x].r].size+1;	
}
void right_rorate(int &now){
	int tmp=tree[now].l;
	tree[now].l=tree[tmp].r;
	tree[tmp].r=now;
	tree[tmp].size=tree[now].size;
	update(now);
	now=tmp;	
}
void left_rorate(int &now){
	int tmp=tree[now].r;
	tree[now].r=tree[tmp].l;
	tree[tmp].l=now;
	tree[tmp].size=tree[now].size;
	update(now);
	now=tmp;
}
inline void insert(int &now,int w){
	if(now==0){
		now=++cnt;
		tree[now].size=1;
		tree[now].val=w;
		tree[now].pri=rand()*rand()%md;
		return;
	}
	tree[now].size++;
	if(w>=tree[now].val){
		insert(tree[now].r,w);
	}
	else{
		insert(tree[now].l,w);
	}
	if(tree[now].l!=0&&tree[now].pri>tree[tree[now].l].pri){
		right_rorate(now);
	}
	if(tree[now].r!=0&&tree[now].pri>tree[tree[now].r].pri){
		left_rorate(now);
	}
	update(now);
}
inline void erase(int &now,int w){
	tree[now].size--;
	if(tree[now].val==w){
		if(tree[now].l==0&&tree[now].r==0){
			now=0;
			return;
		}
		if(tree[now].l==0||tree[now].r==0){//如果没有左儿子或右儿子,那删除当前节点后,当前节点的儿子顶替了当前节点的位置 
			now=tree[now].l+tree[now].r;
			return;
		}
		if(tree[tree[now].l].pri<tree[tree[now].r].pri){
			right_rorate(now);
			erase(tree[now].r,w);
			return;
		} 
		else{
			left_rorate(now);
			erase(tree[now].l,w);
			return;
		}
	}	
	if(tree[now].val>=w){
		erase(tree[now].l,w);
	}
	else{
		erase(tree[now].r,w);
	}
	update(now);
}
inline int rk(int now,int w){
	if(now==0){
		return 0;
	}
	if(w>tree[now].val){
		return tree[tree[now].l].size+1+rk(tree[now].r,w);
	}
	return rk(tree[now].l,w);
}
inline int find(int now,int w){
	if(w==tree[tree[now].l].size+1){
		return tree[now].val;
	}
	if(w>tree[tree[now].l].size+1){
		return find(tree[now].r,w-tree[tree[now].l].size-1);
	}
	return find(tree[now].l,w);
}
void update2(int x){
	tree2[x].size=tree2[tree2[x].l].size+tree2[tree2[x].r].size+1;	
}
void right_rorate2(int &now){
	int tmp=tree2[now].l;
	tree2[now].l=tree2[tmp].r;
	tree2[tmp].r=now;
	tree2[tmp].size=tree2[now].size;
	update2(now);
	now=tmp;	
}
void left_rorate2(int &now){
	int tmp=tree2[now].r;
	tree2[now].r=tree2[tmp].l;
	tree2[tmp].l=now;
	tree2[tmp].size=tree2[now].size;
	update2(now);
	now=tmp;
}
inline void insert2(int &now,int w){
	if(now==0){
		now=++cnt;
		tree2[now].size=1;
		tree2[now].val=w;
		tree2[now].pri=rand()*rand()%md;
		return;
	}
	tree2[now].size++;
	if(w>=tree2[now].val){
		insert2(tree2[now].r,w);
	}
	else{
		insert2(tree2[now].l,w);
	}
	if(tree2[now].l!=0&&tree2[now].pri>tree2[tree2[now].l].pri){
		right_rorate2(now);
	}
	if(tree2[now].r!=0&&tree2[now].pri>tree2[tree2[now].r].pri){
		left_rorate2(now);
	}
	update2(now);
}
inline void erase2(int &now,int w){
	tree2[now].size--;
	if(tree2[now].val==w){
		if(tree2[now].l==0&&tree2[now].r==0){
			now=0;
			return;
		}
		if(tree2[now].l==0||tree2[now].r==0){//如果没有左儿子或右儿子,那删除当前节点后,当前节点的儿子顶替了当前节点的位置 
			now=tree2[now].l+tree2[now].r;
			return;
		}
		if(tree2[tree2[now].l].pri<tree2[tree2[now].r].pri){
			right_rorate2(now);
			erase2(tree2[now].r,w);
			return;
		} 
		else{
			left_rorate2(now);
			erase2(tree2[now].l,w);
			return;
		}
	}	
	if(tree2[now].val>=w){
		erase2(tree2[now].l,w);
	}
	else{
		erase2(tree2[now].r,w);
	}
	update2(now);
}
inline int rk2(int now,int w){
	if(now==0){
		return 0;
	}
	if(w>tree2[now].val){
		return tree2[tree2[now].l].size+1+rk2(tree2[now].r,w);
	}
	return rk2(tree2[now].l,w);
}
inline int find2(int now,int w){
	if(w==tree2[tree2[now].l].size+1){
		return tree2[now].val;
	}
	if(w>tree2[tree2[now].l].size+1){
		return find2(tree2[now].r,w-tree2[tree2[now].l].size-1);
	}
	return find2(tree2[now].l,w);
}
int query_pre2(int now,int w){
	if(now==0){
		return 0;
	}
	if(tree2[now].val>=w){
		return query_pre2(tree2[now].l,w);
	}
	int tmp=query_pre2(tree2[now].r,w);
	if(tmp==0){
		return tree2[now].val;
	}
	return tmp;
}
int query_suf2(int now,int w){
	if(now==0){
		return 0;
	}
	if(tree2[now].val<=w){
		return query_suf2(tree2[now].r,w);
	}
	int tmp=query_suf2(tree2[now].l,w);
	if(tmp==0){
		return tree2[now].val;
	}
	return tmp;
}
//后面的函数和前面的差不多,只是换了个数组                         
void update3(int x){
	tree3[x].size=tree3[tree3[x].l].size+tree3[tree3[x].r].size+1;	
}
void right_rorate3(int &now){
	int tmp=tree3[now].l;
	tree3[now].l=tree3[tmp].r;
	tree3[tmp].r=now;
	tree3[tmp].size=tree3[now].size;
	update3(now);
	now=tmp;	
}
void left_rorate3(int &now){
	int tmp=tree3[now].r;
	tree3[now].r=tree3[tmp].l;
	tree3[tmp].l=now;
	tree3[tmp].size=tree3[now].size;
	update3(now);
	now=tmp;
}
inline void insert3(int &now,int w){
	if(now==0){
		now=++cnt;
		tree3[now].size=1;
		tree3[now].val=w;
		tree3[now].pri=rand()*rand()%md;
		return;
	}
	tree3[now].size++;
	if(w>=tree3[now].val){
		insert3(tree3[now].r,w);
	}
	else{
		insert3(tree3[now].l,w);
	}
	if(tree3[now].l!=0&&tree3[now].pri>tree3[tree3[now].l].pri){
		right_rorate3(now);
	}
	if(tree3[now].r!=0&&tree3[now].pri>tree3[tree3[now].r].pri){
		left_rorate3(now);
	}
	update3(now);
}
inline void erase3(int &now,int w){
	tree3[now].size--;
	if(tree3[now].val==w){
		if(tree3[now].l==0&&tree3[now].r==0){
			now=0;
			return;
		}
		if(tree3[now].l==0||tree3[now].r==0){//如果没有左儿子或右儿子,那删除当前节点后,当前节点的儿子顶替了当前节点的位置 
			now=tree3[now].l+tree3[now].r;
			return;
		}
		if(tree3[tree3[now].l].pri<tree3[tree3[now].r].pri){
			right_rorate3(now);
			erase3(tree3[now].r,w);
			return;
		} 
		else{
			left_rorate3(now);
			erase3(tree3[now].l,w);
			return;
		}
	}	
	if(tree3[now].val>=w){
		erase3(tree3[now].l,w);
	}
	else{
		erase3(tree3[now].r,w);
	}
	update3(now);
}
inline int rk3(int now,int w){
	if(now==0){
		return 0;
	}
	if(w>tree3[now].val){
		return tree3[tree3[now].l].size+1+rk3(tree3[now].r,w);
	}
	return rk3(tree3[now].l,w);
}
inline int find3(int now,int w){
	if(w==tree3[tree3[now].l].size+1){
		return tree3[now].val;
	}
	if(w>tree3[tree3[now].l].size+1){
		return find3(tree3[now].r,w-tree3[tree3[now].l].size-1);
	}
	return find3(tree3[now].l,w);
}
signed main(){
	cin>>n>>m;
	priority_queue<int> q;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i];
		if(i!=1) insert(rt,abs(a[i]-a[i-1]));
		q.push(a[i]);
	}
	int last=-1;
	while(!q.empty()){
		int x=q.top();
		q.pop();
		insert2(rt2,x);
		if(last!=-1) insert3(rt3,abs(x-last));
		last=x;
	}
	for(int i=1;i<=m;i++){
		string s;
		int x,y;
		cin>>s;
		if(s=="INSERT"){
			cin>>x>>y;
			if(x!=n){
				erase(rt,abs(a[x+1]-b[x]));
			}
			insert(rt,abs(y-b[x]));
			if(x!=n){
				insert(rt,abs(a[x+1]-y));
			}
			int p=rk2(rt2,y);
			int fr=query_pre2(rt2,y);
			int lyq=find2(rt2,p+1);
			int sf=query_suf2(rt2,y);
			insert2(rt2,y);
			if(p==0){
				if(lyq==y){
					insert3(rt3,0);
				}	
				else{
					if(sf==0) insert3(rt3,abs(sf-y));
				}
			} 
			else if(sf==0){
				if(lyq==y){
					insert3(rt3,0);
				}
				else{
					insert3(rt3,abs(y-fr));
				}
			}
			else{
				if(lyq==y){
					insert3(rt3,0);
				}
				else{
			    	erase3(rt3,abs(sf-fr));
			    	insert3(rt3,abs(sf-y));
					insert3(rt3,abs(y-fr));
				}
			}
			b[x]=y;
		}
		else if(s=="MIN_SORT_GAP"){
			cout<<find3(rt3,1)<<endl;
		}
		else{
			cout<<find(rt,1)<<endl; 
		}
	}
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...