[loj6498]农民
对每一个节点用二元组$(p,v)$表示,其中$p$是其是父亲的左(0)还是右(1)儿子,$v$是其父亲的点权
$x$合法当且仅当:对于其到根路径上所有$(0,v)$都有$a_{x}<v$、$(1,v)$都有$a_{x}>v$
用树链剖分+线段树来维护这些二元组,即求出$(0,v)$的区间最小值和$(1,v)$的区间最大值即可
对于翻转,即将区间内(是$k$的子树除去$k$的部分)所有$(p,v)$变为$(p\oplus 1,v)$,即区间修改,并再维护$(0,v)$的区间最大值和$(1,v)$的区间最小值即可
(另外翻转后会改变区间,可以再开一棵线段树记录一下每一个点是否被翻转)
时间复杂度为$o(q\log^{2}n)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 #define pii pair<int,int> 8 #define fi first 9 #define se second 10 int rt,n,m,p,x,y,a[N],vis[N],ch[N][2],fa[N],sz[N],son[N],dfn[N],top[N],P[N<<2],tag[N<<2]; 11 pii f[N<<2][2]; 12 void dfs1(int k,int f){ 13 if (!k)return; 14 fa[k]=f; 15 dfs1(ch[k][0],k); 16 dfs1(ch[k][1],k); 17 sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1; 18 son[k]=0; 19 if (sz[ch[k][0]]<sz[ch[k][1]])son[k]=1; 20 } 21 void dfs2(int k,int t){ 22 if (!k)return; 23 dfn[k]=++dfn[0]; 24 top[k]=t; 25 dfs2(ch[k][son[k]],t); 26 dfs2(ch[k][son[k]^1],ch[k][son[k]^1]); 27 } 28 void update_rev(int k,int l,int r,int x,int y){ 29 if ((l>y)||(x>r))return; 30 if ((x<=l)&&(r<=y)){ 31 P[k]^=1; 32 return; 33 } 34 update_rev(L,l,mid,x,y); 35 update_rev(R,mid+1,r,x,y); 36 } 37 int query_rev(int k,int l,int r,int x){ 38 if (l==r)return P[k]; 39 if (x<=mid)return query_rev(L,l,mid,x)^P[k]; 40 return query_rev(R,mid+1,r,x)^P[k]; 41 } 42 pii merge(pii x,pii y){ 43 return make_pair(min(x.fi,y.fi),max(x.se,y.se)); 44 } 45 void up(int k){ 46 for(int i=0;i<2;i++)f[k][i]=merge(f[L][i],f[R][i]); 47 } 48 void upd(int k){ 49 tag[k]^=1; 50 swap(f[k][0],f[k][1]); 51 } 52 void down(int k){ 53 if (tag[k]){ 54 upd(L); 55 upd(R); 56 tag[k]=0; 57 } 58 } 59 void update_val(int k,int l,int r,int x,int y,int p){ 60 if (l==r){ 61 f[k][0]=make_pair(y,0); 62 f[k][1]=make_pair(0x3f3f3f3f,y); 63 if (p)swap(f[k][0],f[k][1]); 64 return; 65 } 66 down(k); 67 if (x<=mid)update_val(L,l,mid,x,y,p); 68 else update_val(R,mid+1,r,x,y,p); 69 up(k); 70 } 71 void update_rev_val(int k,int l,int r,int x,int y){ 72 if ((l>y)||(x>r))return; 73 if ((x<=l)&&(r<=y)){ 74 upd(k); 75 return; 76 } 77 down(k); 78 update_rev_val(L,l,mid,x,y); 79 update_rev_val(R,mid+1,r,x,y); 80 up(k); 81 } 82 pii query_val(int k,int l,int r,int x,int y){ 83 if ((l>y)||(x>r))return make_pair(0x3f3f3f3f,0); 84 if ((x<=l)&&(r<=y))return f[k][0]; 85 down(k); 86 return merge(query_val(L,l,mid,x,y),query_val(R,mid+1,r,x,y)); 87 } 88 void update(int k){ 89 int p=query_rev(1,1,n,dfn[k]); 90 if (ch[k][0])update_val(1,1,n,dfn[ch[k][0]],a[k],p); 91 if (ch[k][1])update_val(1,1,n,dfn[ch[k][1]],a[k],p^1); 92 } 93 pii query(int k){ 94 pii o=make_pair(0x3f3f3f3f,0); 95 while (k){ 96 o=merge(o,query_val(1,1,n,dfn[top[k]],dfn[k])); 97 k=fa[top[k]]; 98 } 99 return o; 100 } 101 int main(){ 102 scanf("%d%d",&n,&m); 103 for(int i=1;i<=n;i++){ 104 scanf("%d%d%d",&a[i],&ch[i][0],&ch[i][1]); 105 vis[ch[i][0]]=vis[ch[i][1]]=1; 106 } 107 for(int i=1;i<=n;i++) 108 if (!vis[i])rt=i; 109 dfs1(rt,0); 110 dfs2(rt,rt); 111 update_val(1,1,n,1,0x3f3f3f3f,0); 112 for(int i=1;i<=n;i++)update(i); 113 for(int i=1;i<=m;i++){ 114 scanf("%d%d",&p,&x); 115 if (p==1){ 116 scanf("%d",&a[x]); 117 update(x); 118 } 119 if (p==2){ 120 update_rev(1,1,n,dfn[x],dfn[x]+sz[x]-1); 121 update_rev_val(1,1,n,dfn[x]+1,dfn[x]+sz[x]-1); 122 } 123 if (p==3){ 124 pii o=query(x); 125 if ((a[x]<o.fi)&&(a[x]>o.se))printf("YES\n"); 126 else printf("NO\n"); 127 } 128 } 129 return 0; 130 }