这个题会卡替罪羊吗
查看原帖
这个题会卡替罪羊吗
132530
cbdsopa楼主2020/11/5 20:00

MLE了

开不了那么多数组

而且数据范围给的有问题吧

#include<bits/stdc++.h>
using namespace std;
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout);
#define MAXN 1500010
int tot,w[MAXN],lc[MAXN],rc[MAXN],cnt[MAXN],size[MAXN],delt[MAXN],rt,fd[MAXN];
double alpha=0.7;
/*
tot 树中元素数量
rt 根节点,rt=0时表示树空
w 点权
lc rc 左右子树
cnt 数值出现个数
size 以本节点为根的子树大小
fd 被删除的点
delt 被删除节点子树大小
alpha 常数,重建比例数 
*/
int n,m,ans;
void calc(int k)//计算以k为根的子树大小 
{
	size[k]=size[lc[k]]+size[rc[k]]+1;
	delt[k]=delt[lc[k]]+delt[rc[k]]+cnt[k];
}
bool canrbu(int k)//判断当前节点是否需要重建 
{
	return cnt[k]&&(alpha*size[k]<=(double)max(size[lc[k]],size[rc[k]]))||((double)delt[k]<=alpha*size[k]); 
} 
void rbu_flatten(int& x,int k)//中序遍历展开k的子树 
{
	if(!k) return;
	rbu_flatten(x,lc[k]);
	if(cnt[k]) fd[x++]=k;
	rbu_flatten(x,rc[k]);
}
int rbu_build(int l,int r)//二分将fd的区间[l,r)重建成树 
{
	int mid=(l+r)>>1;
	if(l>=r) return 0;
	lc[fd[mid]]=rbu_build(l,mid);
	rc[fd[mid]]=rbu_build(mid+1,r);
	calc(fd[mid]);
	return fd[mid];
}
void rbu(int& k)//重建节点k的主函数 
{
	int x=0;
	rbu_flatten(x,k);
	k=rbu_build(0,x);
} 
void insert(int& x,int k)//将值为k的点加入根为x的点中 
{
	if(!x)
	{
		x=++tot;
		if(!rt) rt=1;
		w[x]=k;
		lc[x]=rc[x]=0;
		cnt[x]=size[x]=delt[x]=1;
	}
	else 
	{
		if(w[x]==k) ++cnt[x];
		else if(w[x]<k) insert(rc[x],k);
		else insert(lc[x],k);
		calc(x);
		if(canrbu(x)) rbu(x);
	}
}
void del(int& x,int k)//从x为根的子树中移除一个值为k的点 
{
	if(!k) return;
	else
	{
		if(w[x]==k)
		{
			if(cnt[x]) --cnt[x];
		}
		else
		{
			if(w[x]<k) del(rc[x],k);
			else del(lc[x],k);
		}
		calc(x);
		if(canrbu(x)) rbu(x);
	}
}
int up_bound(int x,int k)//在x的子树中找到大于k的最小数的名次 
{
	if(!x) return 1;
	else if(w[x]==k&&cnt[x])
		return delt[lc[x]]+1+cnt[x];
	else if(k<w[x])
		return up_bound(lc[x],k);
	else return delt[lc[x]]+cnt[x]+up_bound(rc[x],k); 
} 
int up_great(int x,int k)//在x的子树中找到小于k的最大数的名次 
{
	if(!x) return 0;
	else if(w[x]==k&&cnt[x])
		return delt[lc[x]];
	else if(w[x]<k)
		return delt[lc[x]]+cnt[x]+up_great(rc[x],k);
	else return up_great(lc[x],k);
}
int rk(int x)//求值为x的数在树中的排名 
{
	return up_great(rt,x)+1;
}
int kth(int x,int k)//在x的子树中查找名次为k的值 
{
	if(!x) return 0;
	else if(delt[lc[x]]<k&&k<=delt[lc[x]]+cnt[x]) return w[x];
	else if(delt[lc[x]]+cnt[x]<k)
		return kth(rc[x],k-delt[lc[x]]-cnt[x]);
	else return kth(lc[x],k);
}
int pre(int x,int k)//求x的前驱,即小于x的最大数 
{
	return kth(x,up_great(x,k));
}
int nxt(int x,int k)//求x的后继,即大于x的最小值 
{
	return kth(x,up_bound(x,k));
}
int read()
{
	char ch=getchar();
	int s=0,f=1;
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9') {s=s*10+ch-'0';ch=getchar();}
	return s*f;
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)
	{
		int x;
		x=read();
		insert(rt,x);
	}
	int last=0;
	for(int i=1;i<=m;++i)
	{
		int opt,x;
		opt=read();x=read();
		x^=last;
		if(opt==1) 
		{
			insert(rt,x);
		}
		if(opt==2)
		{
			del(rt,x);
		}
		if(opt==3)
		{
			last=rk(x);
			ans^=last;
		}
		if(opt==4)
		{
			last=kth(rt,x);
			ans^=last;
		}
		if(opt==5)
		{
			last=pre(rt,x);
			ans^=last;
		}
		if(opt==6)
		{
			last=nxt(rt,x);
			ans^=last;
		}
	}
	printf("%d",ans);
	return 0;
}

2020/11/5 20:00
加载中...