一道不那么清真的数据结构
题目链接
首先对于没有操作(2)怎么做.
我们考虑对于每个节点,我们要让它小于到根节点道路上所有向左边的父亲节点权值,并且大于所有向右边的路的父亲权值.
我们令每条边的权值是它父亲的权值.
那么,我们用树剖线段树维护所有向右的边和向左的边即可.
现在有操作(2)怎么做呢?
所有向左的边会变成向右,向右的边会变成向左.
那么我们再维护两个值,在线段树上打一个(lazytag)即可.
代码如下
还是有点麻烦的.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define N (100010)
#define inf (0x7f7f7f7f)
#define rg register int
#define Label puts("NAIVE")
#define spa print(' ')
#define ent print('
')
#define rand() (((rand())<<(15))^(rand()))
typedef long double ld;
typedef long long LL;
typedef unsigned long long ull;
using namespace std;
inline char read(){
static const int IN_LEN=1000000;
static char buf[IN_LEN],*s,*t;
return (s==t?t=(s=buf)+fread(buf,1,IN_LEN,stdin),(s==t?-1:*s++):*s++);
}
template<class T>
inline void read(T &x){
static bool iosig;
static char c;
for(iosig=false,c=read();!isdigit(c);c=read()){
if(c=='-')iosig=true;
if(c==-1)return;
}
for(x=0;isdigit(c);c=read())x=((x+(x<<2))<<1)+(c^'0');
if(iosig)x=-x;
}
inline char readchar(){
static char c;
for(c=read();!isalpha(c);c=read())
if(c==-1)return 0;
return c;
}
const int OUT_LEN = 10000000;
char obuf[OUT_LEN],*ooh=obuf;
inline void print(char c) {
if(ooh==obuf+OUT_LEN)fwrite(obuf,1,OUT_LEN,stdout),ooh=obuf;
*ooh++=c;
}
template<class T>
inline void print(T x){
static int buf[30],cnt;
if(x==0)print('0');
else{
if(x<0)print('-'),x=-x;
for(cnt=0;x;x/=10)buf[++cnt]=x%10+48;
while(cnt)print((char)buf[cnt--]);
}
}
inline void flush(){fwrite(obuf,1,ooh-obuf,stdout);}
struct xds{
int rmin,rmax,lmin,lmax,l,r; bool tag;
}a[N<<3];
int n,m,ch[N][2],w[N],dep[N],siz[N],fa[N];
int top[N],son[N],dfn[N],rdfn[N],ind;
void dfs(int u){
int v=ch[u][0],maxsz=-1;
siz[u]=1;
if(v){
dep[v]=dep[u]+1,fa[v]=u;
dfs(v),siz[u]+=siz[v];
if(siz[v]>maxsz)maxsz=siz[v],son[u]=v;
}
v=ch[u][1];
if(v){
dep[v]=dep[u]+1,fa[v]=u;
dfs(v),siz[u]+=siz[v];
if(siz[v]>maxsz)maxsz=siz[v],son[u]=v;
}
}
void dfs2(int u){
if(!u)return;
ind++,dfn[u]=ind,rdfn[ind]=u;
if(son[u])top[son[u]]=top[u],dfs2(son[u]);
int v=ch[u][0];
if(v!=son[u])top[v]=v,dfs2(v);
v=ch[u][1]; if(v!=son[u])top[v]=v,dfs2(v);
}
void pushup(int x){
a[x].rmin=min(a[x*2].rmin,a[x*2+1].rmin);
a[x].rmax=max(a[x*2].rmax,a[x*2+1].rmax);
a[x].lmin=min(a[x*2].lmin,a[x*2+1].lmin);
a[x].lmax=max(a[x*2].lmax,a[x*2+1].lmax);
}
void pushdown(int x){
if(!a[x].tag)return;
a[x*2].tag^=1,a[x*2+1].tag^=1,a[x].tag=0;
swap(a[x].lmin,a[x].rmin);
swap(a[x].lmax,a[x].rmax);
}
bool chk(int u){
return ch[fa[u]][0]==u;
}
void build(int l,int r,int x){
a[x].l=l,a[x].r=r;
if(l==r){
a[x].lmin=a[x].rmin=inf;
if(l==1)return;
if(chk(rdfn[l]))a[x].lmax=a[x].lmin=w[fa[rdfn[l]]];
else a[x].rmax=a[x].rmin=w[fa[rdfn[l]]];
return;
}
int mid=(l+r)>>1;
build(l,mid,x*2),build(mid+1,r,x*2+1);
pushup(x);
}
void change(int k,int v,int x){
if(!k)return;
if(a[x].l==a[x].r){
if(k==1)return;
if(chk(rdfn[k]))a[x].lmax=a[x].lmin=w[fa[rdfn[k]]];
else a[x].rmax=a[x].rmin=w[fa[rdfn[k]]];
return;
}
pushdown(x);
int mid=(a[x].l+a[x].r)>>1;
if(k<=mid)change(k,v,x*2);
else change(k,v,x*2+1);
pushdown(x*2),pushdown(x*2+1);
pushup(x);
}
void modify(int l,int r,int x){
if(l>r)return;
if(a[x].l==l&&a[x].r==r){
a[x].tag^=1;
pushdown(x);
return;
}
pushdown(x);
int mid=(a[x].l+a[x].r)>>1;
if(r<=mid)modify(l,r,x*2);
else if(l>mid)modify(l,r,x*2+1);
else modify(l,mid,x*2),modify(mid+1,r,x*2+1);
pushdown(x*2),pushdown(x*2+1);
pushup(x);
}
void query(int l,int r,int &lmin,int &rmax,int x){
if(a[x].l==l&&a[x].r==r){
lmin=a[x].lmin,rmax=a[x].rmax;
return;
}
pushdown(x),pushdown(x*2),pushdown(x*2+1);
int mid=a[x].l+a[x].r>>1;
if(r<=mid)query(l,r,lmin,rmax,x*2);
else if(l>mid)query(l,r,lmin,rmax,x*2+1);
else{
int lmin1,rmax1,lmin2,rmax2;
query(l,mid,lmin1,rmax1,x*2);
query(mid+1,r,lmin2,rmax2,x*2+1);
lmin=min(lmin1,lmin2),rmax=max(rmax1,rmax2);
}
}
bool query(int u){
int lmin=inf,rmax=-inf,st=u;
if(u==1)return 1;
while(top[u]!=1){
int lm=inf,rm=-inf;
query(dfn[top[u]],dfn[u],lm,rm,1);
lmin=min(lm,lmin);
rmax=max(rm,rmax);
u=fa[top[u]];
}
int lm=inf,rm=-inf;
query(1,dfn[u],lm,rm,1);
lmin=min(lm,lmin);
rmax=max(rm,rmax);
if(w[st]<lmin&&w[st]>rmax)return 1;
else return 0;
}
int main(){
read(n),read(m);
for(int i=1;i<=n;i++)
read(w[i]),read(ch[i][0]),read(ch[i][1]);
dfs(1),top[1]=1,dfs2(1),build(1,n,1);
while(m--){
int op,x,y;
read(op),read(x);
if(op==1)read(y),w[x]=y,change(dfn[ch[x][0]],y,1),change(dfn[ch[x][1]],y,1);
else if(op==2)modify(dfn[x]+1,dfn[x]+siz[x]-1,1);
else if(query(x))puts("YES");else puts("NO");
}
}