题解 农民
发现限制在每个点到根的路径上的每条边上
那么树剖即可,子树 dfs 序连续所以可以直接打标记翻转
复杂度 \(O(n\log^2n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int a[N], ls[N], rs[N], fa[N], rot;
namespace force{
bool query(int x) {
int liml=-INF, limr=INF;
for (int now=x; now!=rot; now=fa[now]) {
if (now==ls[fa[now]]) limr=min(limr, a[fa[now]]-1);
else liml=max(liml, a[fa[now]]+1);
}
return liml<=a[x]&&a[x]<=limr;
}
void dfs(int u) {
if (!u) return ;
swap(ls[u], rs[u]);
dfs(ls[u]); dfs(rs[u]);
}
void solve() {
for (int i=1,op,x,y; i<=m; ++i) {
op=read(); x=read();
if (op==1) a[x]=read();
else if (op==2) dfs(x);
else puts(query(x)?"YES":"NO");
}
}
}
namespace task1{
#define tl(p) tl[p]
#define tr(p) tr[p]
int tl[N<<2], tr[N<<2];
const int leq=1, geq=0;
int siz[N], id[N], tot;
multiset<int> datl[N<<2], datg[N<<2];
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
datl[p].insert(INF), datg[p].insert(-INF);
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void add(int p, int l, int r, int val, int op) {
if (l<=tl(p)&&r>=tr(p)) {
if (op==leq) datl[p].insert(val);
else datg[p].insert(val);
return ;
}
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) add(p<<1, l, r, val, op);
if (r>mid) add(p<<1|1, l, r, val, op);
}
void del(int p, int l, int r, int val, int op) {
if (l<=tl(p)&&r>=tr(p)) {
if (op==leq) datl[p].erase(datl[p].find(val));
else datg[p].erase(datg[p].find(val));
return ;
}
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) del(p<<1, l, r, val, op);
if (r>mid) del(p<<1|1, l, r, val, op);
}
bool query(int p, int pos, int rk, int liml, int limr) {
liml=max(liml, *datg[p].rbegin()), limr=min(limr, *datl[p].begin());
if (tl(p)==tr(p)) {
// int liml=*datg[p].rbegin(), limr=*datl[p].begin();
return liml<=a[rk]&&a[rk]<=limr;
}
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) return query(p<<1, pos, rk, liml, limr);
else return query(p<<1|1, pos, rk, liml, limr);
}
void upd(int x, int val) {
if (ls[x]) del(1, id[ls[x]], id[ls[x]]+siz[ls[x]]-1, a[x]-1, leq);
if (rs[x]) del(1, id[rs[x]], id[rs[x]]+siz[rs[x]]-1, a[x]+1, geq);
a[x]=val;
if (ls[x]) add(1, id[ls[x]], id[ls[x]]+siz[ls[x]]-1, a[x]-1, leq);
if (rs[x]) add(1, id[rs[x]], id[rs[x]]+siz[rs[x]]-1, a[x]+1, geq);
}
void dfs1(int u) {
siz[u]=1; id[u]=++tot;
if (ls[u]) dfs1(ls[u]), siz[u]+=siz[ls[u]];
if (rs[u]) dfs1(rs[u]), siz[u]+=siz[rs[u]];
}
void solve() {
dfs1(rot);
build(1, 1, n);
for (int i=1; i<=n; ++i) {
if (ls[i]) add(1, id[ls[i]], id[ls[i]]+siz[ls[i]]-1, a[i]-1, leq);
if (rs[i]) add(1, id[rs[i]], id[rs[i]]+siz[rs[i]]-1, a[i]+1, geq);
}
for (int i=1,op,x,y; i<=m; ++i) {
op=read(); x=read();
if (op==1) upd(x, read());
else if (op==2) assert(0);
else puts(query(1, id[x], x, -INF, INF)?"YES":"NO");
}
}
}
namespace task{
#define tl(p) tl[p]
#define tr(p) tr[p]
const int leq=1, geq=0;
pair<int, int> liml[N<<2], limg[N<<2];
int tl[N<<2], tr[N<<2], tag[N<<2], rev[N<<2];
int siz[N], msiz[N], mson[N], top[N], rk[N], id[N], tot;
void spread(int p) {
if (!rev[p]) return ;
swap(liml[p<<1], limg[p<<1]), rev[p<<1]^=1;
swap(liml[p<<1|1], limg[p<<1|1]), rev[p<<1|1]^=1;
rev[p]=0;
}
inline void pushup(int p) {
liml[p]={min(liml[p<<1].fir, liml[p<<1|1].fir), max(liml[p<<1].sec, liml[p<<1|1].sec)};
limg[p]={min(limg[p<<1].fir, limg[p<<1|1].fir), max(limg[p<<1].sec, limg[p<<1|1].sec)};
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
liml[p]={INF, INF}, limg[p]={-INF, -INF};
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void add(int p, int pos, int val, int op) {
if (tl(p)==tr(p)) {
if (op==leq) liml[p]={val, val};
else limg[p]={val, val};
return ;
}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) add(p<<1, pos, val, op);
else add(p<<1|1, pos, val, op);
pushup(p);
}
void del(int p, int pos, int val, int op) {
if (tl(p)==tr(p)) {
if (op==leq) liml[p]={INF, INF};
else limg[p]={-INF, -INF};
return ;
}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) del(p<<1, pos, val, op);
else del(p<<1|1, pos, val, op);
pushup(p);
}
void reverse(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) {swap(liml[p], limg[p]); rev[p]^=1; return ;}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) reverse(p<<1, l, r);
if (r>mid) reverse(p<<1|1, l, r);
pushup(p);
}
pair<int, int> query(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return {limg[p].sec, liml[p].fir};
spread(p);
int mid=(tl(p)+tr(p))>>1; pair<int, int> ans={-INF, INF}, t;
if (l<=mid) t=query(p<<1, l, r), ans.fir=max(ans.fir, t.fir), ans.sec=min(ans.sec, t.sec);
if (r>mid) t=query(p<<1|1, l, r), ans.fir=max(ans.fir, t.fir), ans.sec=min(ans.sec, t.sec);
return ans;
}
void dfs1(int u) {
siz[u]=1;
if (ls[u]) dfs1(ls[u]), siz[u]+=siz[ls[u]];
if (rs[u]) dfs1(rs[u]), siz[u]+=siz[rs[u]];
mson[u]=siz[ls[u]]>siz[rs[u]]?ls[u]:rs[u];
}
void dfs2(int u, int t) {
top[u]=t;
rk[id[u]=++tot]=u;
if (!mson[u]) return ;
dfs2(mson[u], t);
if (ls[u]&&ls[u]!=mson[u]) dfs2(ls[u], ls[u]);
if (rs[u]&&rs[u]!=mson[u]) dfs2(rs[u], rs[u]);
}
void upd(int x, int val) {
if (ls[x]) del(1, id[ls[x]], a[x]-1, leq);
if (rs[x]) del(1, id[rs[x]], a[x]+1, geq);
a[x]=val;
if (ls[x]) add(1, id[ls[x]], a[x]-1, leq);
if (rs[x]) add(1, id[rs[x]], a[x]+1, geq);
}
bool query(int x) {
int pos=x;
pair<int, int> lim={-INF, INF};
while (top[x]!=top[rot]) {
pair<int, int> t=query(1, id[top[x]], id[x]);
// cout<<"t: ("<<t.fir<<','<<t.sec<<")"<<endl;
lim.fir=max(lim.fir, t.fir);
lim.sec=min(lim.sec, t.sec);
x=fa[top[x]];
}
pair<int, int> t=query(1, id[rot], id[x]);
// cout<<"t: ("<<t.fir<<','<<t.sec<<")"<<endl;
lim.fir=max(lim.fir, t.fir);
lim.sec=min(lim.sec, t.sec);
// cout<<a[x]<<endl;
return lim.fir<=a[pos]&&a[pos]<=lim.sec;
}
void solve() {
dfs1(rot); dfs2(rot, rot); build(1, 1, n);
for (int i=1; i<=n; ++i) {
if (ls[i]) add(1, id[ls[i]], a[i]-1, leq);
if (rs[i]) add(1, id[rs[i]], a[i]+1, geq);
}
for (int i=1,op,x,y; i<=m; ++i) {
op=read(); x=read();
if (op==1) upd(x, read());
else if (op==2) reverse(1, id[x]+1, id[x]+siz[x]-1);
else puts(query(x)?"YES":"NO");
}
}
}
signed main()
{
n=read(); m=read();
for (int i=1; i<=n; ++i) {
a[i]=read();
fa[ls[i]=read()]=i;
fa[rs[i]=read()]=i;
}
for (int i=1; i<=n; ++i) if (!fa[i]) {rot=i; break;}
// cout<<"rot: "<<rot<<endl;
// if (n<=5000&&m<=5000) force::solve();
// else task1::solve();
// assert(n>5000);
task::solve();
return 0;
}