一个只有数组,循环,条件的简单代码还能怎么RE?
查看原帖
一个只有数组,循环,条件的简单代码还能怎么RE?
68207
CreeperLordVader楼主2021/7/5 08:57

如题,LCT模板题,代码数组开得够大,没有递归和指针,局部变量全部赋值,而且下载了数据本机来跑还跑得飞快,但是交到luogu上哗哗哗全RE,啥情况?

甚至我用这个代码的简化版还AC了洞穴勘测,那代码应该也写的没问题啊

#include<bits/stdc++.h>
#define update(o) sum[o]=sum[ch[o][0]]^v[o]^sum[ch[o][1]]
#define nrt(o) (ch[fa[o]][0]==o||ch[fa[o]][1]==o)
#define chd(o) (ch[fa[o]][1]==o?1:0)
using namespace std;
const int MAXN=100005;
int n,m;
int v[MAXN],sum[MAXN],fa[MAXN],rev[MAXN],ch[MAXN][2];
int s[MAXN],top;
inline void read(int& x)
{
	char c=getchar();
	x=0;
	while(!isdigit(c))c=getchar();
	while(isdigit(c))
	{
		x=(x<<3)+(x<<1)+(c^48);
		c=getchar();
	}
}
inline void rotate(int o)
{
	int p=fa[o],gp=fa[p];
	int d=chd(o);
	if(nrt(p))ch[gp][chd(p)]=o;
	fa[o]=gp;
	ch[p][d]=ch[o][d^1];
	fa[ch[o][d^1]]=p;
	fa[p]=o;
	ch[o][d^1]=p;
	update(p);
}
inline void pushdown(int o)
{
	if(rev[o])
	{
		if(ch[o][0])rev[ch[o][0]]^=1;
		if(ch[o][1])rev[ch[o][1]]^=1;
		swap(ch[o][0],ch[o][1]);
		rev[o]=0;
	}
}
inline void splay(int o)//将o点splay到根,这里要手动完成必需的标记下传,不会下传所有标记 
{
	int x=o;
	while(nrt(x))
	{
		s[++top]=x;//不断上跳,祖先节点在栈的上层 
		x=fa[x];
	}
	s[++top]=x;
	while(top)pushdown(s[top--]);//祖先在栈上层,会先下传祖先标记从而完成标记逐层下传 
	while(nrt(o))
	{
		int p=fa[o];
		if(nrt(p))chd(p)==chd(o)?rotate(p):rotate(o);
		rotate(o);
	}
	update(o);
}
inline void access(int x)
{
	for(int y=0;x;y=x,x=fa[x])//父指针为0,当且仅当它不仅为splay的根,也为原树的根 
	{
		splay(x);
		ch[x][1]=y;
		update(x);
	}//完成access(x)操作后,x不一定是所在splay的根! 
}
inline void makert(int x)
{
	access(x);
	splay(x);
	rev[x]^=1;
	pushdown(x);
}
inline int findrt(int x)//找原树的根,副作用是使x成为splay的根
{
	access(x);
	splay(x);
	pushdown(x);
	while(ch[x][0])//因为splay只下传了部分标记,这里仍然要下传标记 
	{
		pushdown(x);
		x=ch[x][0];
	}
	return x;
}
inline void link(int x,int y)//注意这里连的是轻边,不用修改splay结构 
{
	makert(x);//x变成了所在子树的根,同时也是所在splay的根 
	if(findrt(y)==x)return ;//这个操作使y成为了splay的根 
	fa[x]=y;//因为x是所在splay的根,所以可以把这个原树直接用fa[x]=y连一条轻边成为y的子树 
}
inline void cut(int x,int y)
{
	makert(x);
	if(findrt(y)!=x)return ;//注意如果findrt(y)==x,那么一定已经完成了access(y),y和x在一条实路径中,findrt后y为splay的根 
	if(ch[y][0]!=x)return ;//此时x,y在同一棵splay中,若x,y有实边连接(因为access),x一定为y的左儿子 
	fa[x]=ch[y][0]=0;
	update(x);
	update(y);
}
inline void split(int x,int y)//将x-y的路径变成完整的实路径并使y成为splay的根 
{
	makert(x);
	access(y);
	splay(y);
}
inline int query(int x,int y)
{
	split(x,y);
	return sum[y]; 
}
inline int change(int x,int k)
{
	splay(x);
	v[x]=k;
	update(x);
}
int main()
{
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout); 
	read(n);
	read(m);
	for(int i=1;i<=n;i++)read(v[i]);
	for(int i=1;i<=m;i++)
	{
		int op,x,y;
		read(op);
		read(x);
		read(y);
		if(!op)printf("%d\n",query(x,y));
		else if(op==1)link(x,y);
		else if(op==2)cut(x,y);
		else change(x,y);
	}
}
2021/7/5 08:57
加载中...