Abendsen assigned a mission to Juliana. In this mission, Juliana has a rooted tree with q queries. Each query is one of three types:
- If vertex v instead.
- Mark all vertices in the subtree of v) as white.
- Find the color of the i-th vertex.
Can you help Juliana to process all these queries?
The first line contains two integers 1≤q≤105) — the number of vertices and the number of queries.
The second line contains pi.
Each of the next i-th query.
It is guaranteed that the given graph is a tree.
For each query of type
题意:给你一颗树,树上一开始点的颜色全是白色。然后有三种操作:1.把一个白色的点v染成黑色,如果该点v本就是黑色,则对他的所有直接子节点做操作1。2.将节点v的子树全部染成白色。3.查询节点v的颜色。对于每个操作3输出其颜色。
题解:我们要使其在一个尽量平均的时间内进行求解,就需要将其改造成一个相对平衡的树,那我们就考虑用树链刨分对这颗树进行分解。我们发觉每个操作1对应使该点所在的一条重链所对应的区间黑色区间右端点后移一位,其他影响到的重链也后移一位。因此我们查询点v是否为黑色,就看从根到v点的所有链对应的区间上,任何黑色区间右端点位移位置是否超过该点v。我们对线段树维护两个值,一个是端点对应区间剩余白色点的个数leaf(可为负数,即透支后面的链的白色点数),另一个是对应区间中最靠右侧的黑色区间的右端点超出该区间右端点距离(也就是我们上文说到的对其他重链的影响长度)execr,一开始是-1因为右端点还是白色。剩余白色点的转移就是子区间白色点数相加,而第二个维护量execr(即向区间右端点后边区间的影响长度)的转移则是max(右子区间execr,左子区间execr-右子区间leaf)。这样我们查询的时候就能通过该点向后影响长度来查询该点是不是被染成黑色。>=0就是被染色了,-1则是未染色。对于操作1,直接对对应的线段树上的单点v的区间的execr++,leaf--。对于操作3,我们将根节点到节点v的所有区间连起来,算算execr是不是>-1,若是则染色了。对于操作2,我们则直接把所有对应的区间清0,即leaf为区间点数,execr为-1。为了防止v的祖先节点对v子树区间的影响,我们对v做操作3查询超出长度k,若>-1,则反向对v点做操作1(k+1)次,即execr-=(k+1),leaf+=(k+1)。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define INF 0x3f3f3f3f 5 #define LL long long 6 #define pb push_back 7 #define ls(i) (i<<1) 8 #define rs(i) (i<<1|1) 9 #define mp make_pair 10 #define fi first 11 #define se second 12 #define mod 1000000007 13 using namespace std; 14 const int N=2e5+100; 15 vector<int> e[N]; 16 int fa[N]; 17 struct seg 18 { 19 int l,r,execr,leaf; 20 bool tag; 21 }tree[N<<2]; 22 int n,m,k,q; 23 int t,v; 24 void pushup(int i) 25 { 26 tree[i].leaf=tree[i<<1].leaf+tree[i<<1|1].leaf; 27 tree[i].execr=max(tree[i<<1|1].execr,tree[i<<1].execr-tree[i<<1|1].leaf); 28 return ; 29 } 30 void init(int i,int l,int r) 31 { 32 tree[i]=(seg){l,r,-1,1,false}; 33 if(l==r) 34 return ; 35 int mid=l+r>>1; 36 init(i<<1,l,mid); 37 init(i<<1|1,mid+1,r); 38 pushup(i); 39 return ; 40 } 41 int top[N],son[N],pre[N],las[N],stot[N],dep[N]; 42 int tot; 43 void dfs1(int u,int f,int deep) 44 { 45 stot[u]=1; 46 dep[u]=deep; 47 fa[u]=f; 48 for(auto p:e[u]) 49 { 50 if(p==f) continue; 51 dfs1(p,u,deep+1); 52 stot[u]+=stot[p]; 53 if(son[u]==0 || stot[son[u]]<stot[p]) 54 son[u]=p; 55 } 56 return ; 57 } 58 void dfs2(int u,int tp) 59 { 60 pre[u]=++tot; 61 top[u]=tp; 62 if(son[u]) dfs2(son[u],tp); 63 for(auto p:e[u]) 64 { 65 if(p==son[u] || p==fa[u]) 66 continue; 67 dfs2(p,p); 68 } 69 las[u]=tot; 70 return ; 71 } 72 void pushdown(int i) 73 { 74 if(tree[i].l!=tree[i].r) 75 { 76 tree[i<<1].tag=tree[i<<1|1].tag=1; 77 tree[i<<1].leaf=tree[i<<1].r-tree[i<<1].l+1,tree[i<<1].execr=-1; 78 tree[i<<1|1].leaf=tree[i<<1|1].r-tree[i<<1|1].l+1,tree[i<<1|1].execr=-1; 79 } 80 tree[i].tag=0; 81 return ; 82 } 83 void update(int i,int l,int r,int val) 84 { 85 if(tree[i].l>=l && tree[i].r<=r) 86 { 87 if(val==INF)//都是区间修改 88 tree[i].leaf=tree[i].r-tree[i].l+1,tree[i].execr=-1,tree[i].tag=1; 89 else 90 tree[i].leaf-=val,tree[i].execr+=val,tree[i].tag=0;//都是单点修改 91 return ; 92 } 93 if(tree[i].tag) pushdown(i); 94 int mid=tree[i].l+tree[i].r>>1; 95 if(l<=mid) update(i<<1,l,r,val); 96 if(r>mid) update(i<<1|1,l,r,val); 97 pushup(i); 98 return ; 99 } 100 struct ret{ 101 int execr,leaf; 102 }; 103 ret operator + (const ret &a,const ret &b) 104 { 105 ret c; 106 c.leaf=a.leaf+b.leaf; 107 c.execr=max(b.execr,a.execr-b.leaf); 108 return c; 109 } 110 ret query(int i,int l,int r) 111 { 112 if(tree[i].l>=l && tree[i].r<=r) 113 return (ret){tree[i].execr,tree[i].leaf}; 114 if(tree[i].tag) pushdown(i); 115 int mid=tree[i].l+tree[i].r>>1; 116 ret retur=(ret){-INF,0}; 117 if(r>mid) retur=query(i<<1|1,l,r)+retur; 118 if(l<=mid) retur=query(i<<1,l,r)+retur; 119 return retur; 120 } 121 int que(int x) 122 { 123 int tx=top[x]; 124 ret retur=(ret){-INF,0},per; 125 while(tx!=1) 126 { 127 per=query(1,pre[tx],pre[x]); 128 retur=per+retur; 129 x=fa[tx],tx=top[x]; 130 } 131 per=query(1,pre[tx],pre[x]); 132 retur=per+retur; 133 return retur.execr; 134 } 135 int main() 136 { 137 ios::sync_with_stdio(false); 138 cin.tie(0); 139 cout.tie(0); 140 cin>>n>>q; 141 for(int i=2;i<=n;i++) 142 { 143 cin>>v; 144 e[v].pb(i); 145 e[i].pb(v); 146 } 147 init(1,1,n); 148 dfs1(1,1,1); 149 dfs2(1,1); 150 for(int i=1;i<=q;i++) 151 { 152 cin>>t>>v; 153 if(t==1) 154 update(1,pre[v],pre[v],1); 155 else if(t==2) 156 { 157 update(1,pre[v],las[v],INF); 158 t=que(v); 159 if(t>-1) 160 update(1,pre[v],pre[v],-(t+1)); 161 } 162 else if(t==3) 163 { 164 t=que(v); 165 cout<<(t>-1?"black":"white")<<endl; 166 } 167 } 168 return 0; 169 }