Consider the point query of the tree array interval modification (which affects only the answers to its subtree), and each point records its weight-to-value XOR on the root path.
Answer when query (L) ^query (R) ^a[lca].
This method avoids tree chain splits when asked on a tree that supports interval addition and subtraction.
May explode stack, consider manual open stack. (Eh eh Tarjan pretreatment LCA when did not manually open the stack?) Don't mind ^_^)
It's not actually going to explode.
#include <cstdio> #include <stack> #include <algorithm> #include <queue> #include <cmath> #include <vector>using namespace std; #define N 500001typedef pair<int,int> point;vector<point>ask[n ];int N,a[n],b[n],m,ancestor[n];int En,first[n],next[n<<1],v[n<<1];int FA[N],rank[N],lcas[N];void Addedge (const int &u,const int &v) {v[++en]=v;next[en]=first[u];first[u]=en;} int findroot (int x) {return fa[x]==x?x:findroot (fa[x]);} void Union (int x,int y) {int u=findroot (x); int V=findroot (y); if (Rank[u]<rank[v]) fa[u]=v;else {fa[v]=u; if (Rank[u]==rank[v]) ++rank[u]; }}bool vis[n];void LCA (int u,int Fa) {ancestor[u]=u;for (int i=first[u];i;i=next[i]) if (V[I]!=FA) {LCA (v[i],u); Union (U,v[i]); Ancestor[findroot (U)]=u; }vis[u]=1;for (int i=0;i<ask[u].size (); i++) if (Vis[ask[u][i].first]) lcas[ask[u][i].second]=ancestor[findroot ( Ask[u][i].first)];} Stack<int>st;queue<int>q;int tot,lS[n],rs[n],root=1;void Dfs () {st.push (1); Ls[1]=++tot;b[1]=a[1];while (!st.empty ()) {int u=st.top (); bool flag=0; for (int i=first[u];i;i=next[i]) if (! Ls[v[i]]) {ls[v[i]]=++tot; B[v[i]]= (A[v[i]]^b[u]); St.push (V[i]); First[u]=next[i]; flag=1; Break } if (!flag) {rs[u]=tot; St.pop (); }}}int d[n];void add_node (int p,const int &v) {for (;p <=n;p+= (-P)) p&;} void Add_range (const int &L,CONST int &r,const int &v) {Add_node (l,v), if (r!=n) Add_node (r+1,v);} int query (int p) {int res=0;for (;p; p-= (-P)) Res^=d[p];return res;} int a[n],b[n]; Char Op[n][2];int main () {int x,y;scanf ("%d", &n), for (int i=1;i<=n;++i) {fa[i]=i; scanf ("%d", &a[i]); }for (int i=1;i<n;++i) {scanf ("%d%d", &x,&y); Addedge (x, y); Addedge (Y,X); }SCANF ("%d", &m), for (int i=1;i<=m;++i) {scanf ("%s%d%d", Op[i],&a[i],&b[i]), if (op[i][0]== ' Q ') {ask[a[ I]].push_back (Make_pair (b[i],i)); Ask[b[i]]. Push_back (Make_pair (a[i],i)); }}LCA (1,0);d FS (), for (int i=1;i<=n;++i) Add_range (Ls[i],ls[i],b[i]), for (int i=1;i<=m;++i) if (op[i][0]== ' Q ') Puts ((query (Ls[a[i]) ^query (Ls[b[i]]) ^a[lcas[i]])? " Yes ":" No "); else {add_range (ls[a[i]],rs[a[i]],a[a[i]]^b[i]); A[a[i]]=b[i]; }return 0;}
"Manual Open Stack" "Dfs Order" "Tree Array" "Tarjan" bzoj2819 Nim