LOJ#6498. 「雅礼集训 2018 Day2」农民 题解

题目链接

不难发现,一条父亲到左儿子的边相当于一个\(\texttt{<}\)限制,一条父亲到右儿子的边相当于一个\(\texttt>\)限制。

考虑用树链剖分维护这些限制,2操作直接线段树上打tag,把\(\texttt<\)限制和\(\texttt>\)限制交换一下即可。

\(\Theta(n\log^2 n)\)

code :

#include <bits/stdc++.h>
using namespace std;
template <typename T> void read(T &x){
	static char ch; x = 0,ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }

const int INF = 1e9 + 7,N = 100005;
int n,m,rt,a[N],fa[N],ch[N][2],z[N];

int dpt[N],son[N],size[N];
inline void dfs1(int x){
	dpt[x] = dpt[fa[x]] + 1,size[x] = 1;
	for (int i = 0,y; i < 2; ++i) if (y=ch[x][i]){
		dfs1(y),size[x] += size[y];
		if (size[y] > size[son[x]]) son[x] = y;
	}
}
int top[N];
int Time,id[N],tl[N],tr[N],node[N];
inline void dfs2(int x){
	id[x] = tl[x] = ++Time; node[Time] = x;
	if (son[x]) top[son[x]] = top[x],dfs2(son[x]);
	for (int i = 0,y; i < 2; ++i) if (ch[x][i] && !top[y=ch[x][i]]) top[y] = y,dfs2(y);
	tr[x] = Time;
}

struct Node{
	int mx,mn;
	Node(int Mx = -INF,int Mn = INF){ mx = Mx,mn = Mn; }
}f0[N<<2],f1[N<<2]; bool rev[N<<2];
Node operator + (Node A,Node B){ return Node(max(A.mx,B.mx),min(A.mn,B.mn)); }

#define lc o<<1
#define rc o<<1|1
inline void up(int o){ f0[o] = f0[lc] + f0[rc],f1[o] = f1[lc] + f1[rc]; }
inline void Build(int o,int l,int r){
	if (l ^ r){ int mid = l+r>>1; Build(lc,l,mid); Build(rc,mid+1,r); up(o); return; }
	if (fa[node[l]]){
		if (z[node[l]]) f1[o] = Node(a[fa[node[l]]],a[fa[node[l]]]);
		else f0[o] = Node(a[fa[node[l]]],a[fa[node[l]]]);
	}
}
int ll,rr,pp;
inline void Tag(int o){ if (o) rev[o] ^= 1,swap(f0[o],f1[o]); }
inline void down(int o){ if (rev[o]) Tag(lc),Tag(rc),rev[o] = 0; }
inline void Modify(int o,int l,int r){
	if (l == r){
		f0[o] = f1[o] = Node();
		z[node[l]] ^= rev[o],rev[o] = 0;
		if (fa[node[l]]){
			if (z[node[l]]) f1[o] = Node(a[fa[node[l]]],a[fa[node[l]]]);
			else f0[o] = Node(a[fa[node[l]]],a[fa[node[l]]]);
		}
		return;
	}
	down(o); int mid = l+r>>1; if (pp <= mid) Modify(lc,l,mid); else Modify(rc,mid+1,r); up(o);
}
inline void Rev(int o,int l,int r){
	if (ll <= l && rr >= r){ Tag(o); return; }
	down(o); int mid = l+r>>1; if (ll <= mid) Rev(lc,l,mid); if (rr > mid) Rev(rc,mid+1,r); up(o);
}
Node q0,q1;
inline void Ask(int o,int l,int r){
	if (ll <= l && rr >= r){ q0 = q0 + f0[o],q1 = q1 + f1[o]; return; }
	down(o); int mid = l+r>>1; if (ll <= mid) Ask(lc,l,mid); if (rr > mid) Ask(rc,mid+1,r); 
}
inline bool Query(int x){
	int v = a[x]; q0 = q1 = Node();
	while (x) ll = id[top[x]],rr = id[x],Ask(1,1,n),x = fa[top[x]];
	return q1.mx < v && v < q0.mn;
}
#undef lc
#undef rc

int main(){
	int i;
	read(n),read(m);
	for (i = 1; i <= n; ++i){
		read(a[i]),read(ch[i][0]),read(ch[i][1]);
		if (ch[i][0]) fa[ch[i][0]] = i;
		if (ch[i][1]) fa[ch[i][1]] = i,z[ch[i][1]] = 1;
	}
	for (i = 1; i <= n; ++i) if (!fa[i]) rt = i;
	dfs1(rt),top[rt] = rt,dfs2(rt);
	Build(1,1,n);
	int op,x;
	while (m--){
		read(op),read(x);
		if (op == 1){
			read(a[x]);
			if (ch[x][0]) pp = id[ch[x][0]],Modify(1,1,n);
			if (ch[x][1]) pp = id[ch[x][1]],Modify(1,1,n);
		}
		if (op == 2){
			ll = tl[x]+1,rr = tr[x]; if (ll <= rr) Rev(1,1,n); 
		}
		if (op == 3){
			puts(Query(x) ? "YES" : "NO");
		}
	}
	return 0;
}
posted @ 2020-09-08 20:57  srf  阅读(283)  评论(0编辑  收藏  举报