下载数据本地过了但是WA
查看原帖
下载数据本地过了但是WA
221982
月影舞纵丶楼主2023/9/1 13:02
#include<cstdio>
#include<stdlib.h>
#include<iostream>
const int N=1e5+11,INF=0x7f7f7f7f;
struct Treap{
	int val,dat;
	int l,r;
	int cnt,size;
}a[N];
int tot,root,p_d,p_i;//p_d是总共删除了多少个结点,内置在delete函数内的一个计数器,p_i是总共加入了多少个员工 

int n,min;
int td; //td是总共全体员工上调/扣除的工资 

int New(int val){
	a[++tot].val=val;
	a[tot].dat=rand();
	a[tot].cnt=a[tot].size=1;
	return tot;
}

void Update(int p){
	a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
}

void Build(){ //为了保证-INF删不掉,且不影响删其他点,固定其为根节点 
	New(-INF);New(INF);
	a[1].dat=0x7f7f7f7f;
	a[1].r=2;
	root=1;
	Update(1);
}

void zig(int &p){
	int q=a[p].l;
	a[p].l=a[q].r;
	a[q].r=p;
	p=q;  //这一步是为了让之前p的父节点连接到q上
	Update(p);Update(a[p].r); 
}

void zag(int &p){
	int q=a[p].r;
	a[p].r=a[q].l;
	a[q].l=p;
	p=q;
	Update(p);Update(a[p].l);
}

void Insert(int &p,int val){
	//printf("插入:p=%d\n val=%d\n",p,val); 
	if(p==0){
		p=New(val);
		return;
	}
	if(a[p].val==val){
		a[p].cnt++;
		Update(p);
		return;
	}
	if(val<a[p].val){
		Insert(a[p].l,val);
		if(a[p].dat<a[a[p].l].dat) zig(p);
	}
	if(val>a[p].val){
		Insert(a[p].r,val);
		if(a[p].dat<a[a[p].r].dat) zag(p);
	}
	Update(p); //每次往上回溯前必须Update! 
}

void Delete(int &p){ //一定没有左儿子 
	//printf("p=%d a[p].val=%d\n",p,a[p].val);
	//printf("l=%d  r=%d\n",a[p].l,a[p].r);
	if(a[p].r){ //如果有右儿子 
		zag(p);
		Delete(a[p].l);
		Update(p); 
	}
	else if(a[p].l==0&&a[p].r==0){ //已经是叶结点了 
		//printf("删除:a[p].cnt=%d\n",a[p].cnt); 
		p_d+=a[p].cnt; //计数器加上p的cnt 
		p=0; //删除掉这个结点 
	}
	return; 
}

void Clear(int &p,int val){ //去掉关键码≤val的所有结点 
	if(p==0) return;
	if(val<a[p].val) {
		Clear(a[p].l,val); //只进入左子树 
		Update(p);
	}
	else {
		Clear(a[p].r,val);
		Clear(a[p].l,val); //左右子树都进入 
		Update(p); //是否多余了? 
	}
	//printf("Clear_val=%d\n",val);
	if(a[p].val<=val&&p!=1) Delete(p); //回溯时,如果该节点符合条件,需要被删除
	//注意到删除的时候,该结点的左子树一定被删完了,所以将其左旋一下就到叶节点了,就可以直接删除 
}

int getval(int p,int x){ //返回在p的子树中排名为x的结点的值  
	//printf("Get_val:p=%d x=%d\n",p,x);
	//printf("a[a[p].l].size=%d  a[p].cnt=%d\n",a[a[p].l].size,a[p].cnt);
	if(p==0) return -1;
	if(a[a[p].l].size>=x) return getval(a[p].l,x);
	else if(a[a[p].l].size<x&&a[a[p].l].size+a[p].cnt>=x) return a[p].val;
	else return getval(a[p].r,x-a[a[p].l].size-a[p].cnt);
}

int main(){
	//freopen("P1486_2.in","r",stdin);
	//freopen("ans.txt","w",stdout);
	Build();
	scanf("%d%d",&n,&min);
	for(int i=1;i<=n;i++){
		//getchar();
		//char x=getchar();int k;
		char x;int k;
		//scanf("%d",&k);
		std::cin>>x>>k;
		//printf("x=%c\n",x);
		if(x=='I'){
			//printf("插入:td=%d\n",td);
			if(k<min) continue;
			else {
				Insert(root,k-td); //为了加入新员工时不受之前加减工资的影响,在插入时就直接带入原来的增加工资 
				p_i++;
			}
		}
		else if(x=='A') td+=k;
		else if(x=='S'){
			td-=k;
			Clear(root,min-td-1); //当前工资比min小的被清除 
		}
		else if(x=='F') {
			//printf("p_i=%d p_d=%d k=%d\n",p_i,p_d,k);
			if(p_i+2-k-p_d<=1) std::cout<<-1<<std::endl;
			else {
				
				std::cout<<getval(root,p_i+2-k-p_d)+td<<std::endl;
			}
		}
	}
	//for(int p=1;p<=tot;p++) printf("p=%d val=%d cnt=%d size=%d l=%d r=%d\n",p,a[p].val,a[p].cnt,a[p].size,a[p].l,a[p].r); 
	std::cout<<p_d<<std::endl;
	return 0;
}

自己写的Treap,提交只有30pts,但是下载数据在本地运行答案是正确的,求助大佬们

2023/9/1 13:02
加载中...