cbdsopa @ 2020-11-05 20:00:09
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;
}
by UltiMadow @ 2020-11-05 20:03:32
没卡替罪羊啊,我用替罪羊写的过了(
by cbdsopa @ 2020-11-05 20:04:46
那我写的太丑了吧,MLE第6个点
by cbdsopa @ 2020-11-05 20:12:18
应该哪个递归爆了
by 胖头鱼学员 @ 2020-11-06 08:30:58
很显然,有些操作冗余的,或者是哪里没处理好。
by cbdsopa @ 2020-11-06 13:55:20
过了,x打成k了