如题,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);
}
}