今天看到这道题,忽然不知道为何要线段树了笑(出现了一些瞎搞的想法
然后就想到了操作树。。。
就是,我们可以离线,然后每个位置直接维护一个栈,记录历史信息。
然鹅我也不知道为什么常数很大
#include<bits/stdc++.h>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=200010;
int n,m;
bool ans[N];
struct node {bool op,f[2],flg[2]; int u,v,tu,tv;}mem[N<<1];
vector <int> fa[N],d[N];
vector <int> e[N];
inline int getf(int x) {return (fa[x][fa[x].size()-1]==x)?x:getf(fa[x][fa[x].size()-1]);}
inline void operation(int x) {
if(!mem[x].op) {
mem[x].tu=getf(mem[x].u),mem[x].tv=getf(mem[x].v); R u=mem[x].tu,v=mem[x].tv;
if(d[u][d[u].size()-1]<d[v][d[v].size()-1]) swap(u,v);
fa[v].push_back(u); mem[x].f[v==mem[x].tv]=true;
if(d[u][d[u].size()-1]==d[v][d[v].size()-1]) d[u].push_back(d[u][d[u].size()-1]+1),mem[x].flg[u==mem[x].tv]=true;
} else ans[x]=getf(mem[x].u)==getf(mem[x].v);
}
inline void undo(int x) {
if(mem[x].f[0]) fa[mem[x].tu].pop_back();
else fa[mem[x].tv].pop_back();
if(mem[x].flg[0]) d[mem[x].tu].pop_back();
else if(mem[x].flg[1]) d[mem[x].tv].pop_back();
}
inline void dfs(int u) {
if(mem[u].u) operation(u);
for(R v:e[u]) dfs(v);
if(mem[u].u&&!mem[u].op) undo(u);
}
inline void main() {
n=g(),m=g(); for(R i=1;i<=n;++i) fa[i].push_back(i),d[i].push_back(1);
for(R i=1,op;i<=m;++i) {
op=g(); if(op==1) mem[i].u=g(),mem[i].v=g(),e[i-1].push_back(i);
else if(op==2) op=g(),e[op].push_back(i);
else if(op==3) mem[i].op=1,mem[i].u=g(),mem[i].v=g(),e[i-1].push_back(i);
} dfs(0); for(R i=1;i<=m;++i) if(mem[i].op) printf("%d
",ans[i]);
}
} signed main() {Luitaryi::main(); return 0;}
2019.11.21