今天看到这道题,忽然不知道为何要线段树了\笑(出现了一些瞎搞的想法
然后就想到了操作树。。。
就是,我们可以离线,然后每个位置直接维护一个栈,记录历史信息。然鹅我也不知道为什么常数很大
#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\n",ans[i]); } } signed main() {Luitaryi::main(); return 0;}
2019.11.21