神仙题。

首先不考虑把黑点变白,发现每个白点的信息与它的归属点是相同的。可以在线段树中只维护黑点的信息,再记录$DFS$序上每个点之前黑点个数的前缀和,每次操作可以二分出该点的归属点进行操作。

具体维护黑点管辖点的个数与它的权值,及前两者乘积之和。一些其他的点数可以通过子树大小减管辖点总和得到。两个修改操作直接线段树上修改即可。

再考虑黑点变白的情况。每次把黑点变白后,它管辖点的归属点改变,但权值不变,可以在线段树中记录下当前点真实权值与它归属点权值的差,删点时做子树加,每次询问用归属点的权值加上这个差值。

但这个点的子树中还有归属点不变的点,通过$4$操作再把多加上的权值减掉。

  1 #include<bits/stdc++.h>
2 #define int unsigned int
3 using namespace std;
4
5 namespace IO{
6 inline int read(){
7 int x=0,f=1; char ch=getchar();
8 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
9 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
10 return x*f;
11 }
12 inline void write(int x,char sp){
13 char ch[20]; int len=0;
14 if(x<0){ putchar('-'); x=~x+1; }
15 do{ ch[len++]=x%10+(1<<5)+(1<<4); x/=10; }while(x);
16 for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
17 }
18 } using namespace IO;
19
20 const int NN=3e5+5;
21 int n,m,idx,to[NN<<1],nex[NN<<1],head[NN],col[NN];
22 int opt,k,w;
23 inline void add(int a,int b){
24 to[++idx]=b; nex[idx]=head[a]; head[a]=idx;
25 to[++idx]=a; nex[idx]=head[b]; head[b]=idx;
26 }
27
28 namespace BIT{
29 struct bit{
30 int c[NN];
31 inline void insert(signed pos,int x){
32 while(pos<=n){
33 c[pos]+=x;
34 pos+=(pos&(-pos));
35 }
36 }
37 inline int query(signed pos){
38 int res=0;
39 while(pos){
40 res+=c[pos];
41 pos-=(pos&(-pos));
42 }
43 return res;
44 }
45 }bl;
46 } using namespace BIT;
47
48 namespace segment_tree{
49 #define ld rt<<1
50 #define rd (rt<<1)|1
51 int num[NN<<2],val[NN<<2],sum[NN<<2],ch[NN<<2],laz[NN<<2],lac[NN<<2];
52 inline void pushup(int rt){
53 num[rt]=num[ld]+num[rd];
54 sum[rt]=sum[ld]+sum[rd];
55 val[rt]=val[ld]+val[rd];
56 ch[rt]=ch[ld]+ch[rd];
57 }
58 inline void pushdown(int rt,int l,int r){
59 if(laz[rt]){
60 sum[ld]+=laz[rt]*num[ld]; sum[rd]+=laz[rt]*num[rd];
61 val[ld]+=laz[rt]; val[rd]+=laz[rt];
62 laz[ld]+=laz[rt]; laz[rd]+=laz[rt];
63 }
64 if(lac[rt]){
65 int mid=l+r>>1;
66 ch[ld]+=lac[rt]*(mid-l+1); ch[rd]+=lac[rt]*(r-mid);
67 lac[ld]+=lac[rt]; lac[rd]+=lac[rt];
68 }
69 laz[rt]=lac[rt]=0;
70 }
71 void insert(int rt,int l,int r,int pos,int nu,int v){
72 if(l==r){
73 num[rt]=nu; val[rt]=v; sum[rt]=nu*v;
74 return;
75 }
76 pushdown(rt,l,r);
77 int mid=l+r>>1;
78 if(pos<=mid) insert(ld,l,mid,pos,nu,v);
79 else insert(rd,mid+1,r,pos,nu,v);
80 pushup(rt);
81 }
82 void delet(int rt,int l,int r,int pos){
83 if(l==r){
84 sum[rt]=num[rt]=val[rt]=0;
85 return;
86 }
87 pushdown(rt,l,r);
88 int mid=l+r>>1;
89 if(pos<=mid) delet(ld,l,mid,pos);
90 else delet(rd,mid+1,r,pos);
91 pushup(rt);
92 }
93 void update(int rt,int l,int r,int opl,int opr,int v){
94 if(l>=opl&&r<=opr){
95 val[rt]+=v;
96 sum[rt]+=v*num[rt];
97 laz[rt]+=v;
98 return;
99 }
100 pushdown(rt,l,r);
101 int mid=l+r>>1;
102 if(opl<=mid) update(ld,l,mid,opl,opr,v);
103 if(opr>mid) update(rd,mid+1,r,opl,opr,v);
104 pushup(rt);
105 }
106 void modify(int rt,int l,int r,int opl,int opr,int v){//差
107 if(l>=opl&&r<=opr){
108 ch[rt]+=v*(r-l+1);
109 lac[rt]+=v;
110 return;
111 }
112 pushdown(rt,l,r);
113 int mid=l+r>>1;
114 if(opl<=mid) modify(ld,l,mid,opl,opr,v);
115 if(opr>mid) modify(rd,mid+1,r,opl,opr,v);
116 pushup(rt);
117 }
118 int queryc(int rt,int l,int r,int opl,int opr){
119 if(l>=opl&&r<=opr) return ch[rt];
120 pushdown(rt,l,r);
121 int mid=l+r>>1; int ans=0;
122 if(opl<=mid) ans+=queryc(ld,l,mid,opl,opr);
123 if(opr>mid) ans+=queryc(rd,mid+1,r,opl,opr);
124 return ans;
125 }
126 int querys(int rt,int l,int r,int opl,int opr){
127 if(l>=opl&&r<=opr) return sum[rt];
128 pushdown(rt,l,r);
129 int mid=l+r>>1; int ans=0;
130 if(opl<=mid) ans+=querys(ld,l,mid,opl,opr);
131 if(opr>mid) ans+=querys(rd,mid+1,r,opl,opr);
132 return ans;
133 }
134 int queryn(int rt,int l,int r,int opl,int opr){
135 if(l>=opl&&r<=opr) return num[rt];
136 pushdown(rt,l,r);
137 int mid=l+r>>1; int ans=0;
138 if(opl<=mid) ans+=queryn(ld,l,mid,opl,opr);
139 if(opr>mid) ans+=queryn(rd,mid+1,r,opl,opr);
140 return ans;
141 }
142 int queryv(int rt,int l,int r,int pos){
143 if(l==r) return val[rt];
144 pushdown(rt,l,r);
145 int mid=l+r>>1;
146 if(pos<=mid) return queryv(ld,l,mid,pos);
147 if(pos>mid) return queryv(rd,mid+1,r,pos);
148 }
149 } using namespace segment_tree;
150
151 namespace Tree_Division{
152 int dep[NN],dfn[NN],id[NN],top[NN],fa[NN],siz[NN],son[NN],cnt;
153 void dfs1(int s,int f){
154 fa[s]=f; siz[s]=1; dep[s]=dep[f]+1;
155 for(int i=head[s];i;i=nex[i]){
156 int v=to[i];
157 if(v==f) continue;
158 dfs1(v,s);
159 siz[s]+=siz[v];
160 if(siz[son[s]]<siz[v]) son[s]=v;
161 }
162 }
163 void dfs2(int s,int t){
164 top[s]=t; dfn[s]=++cnt; id[cnt]=s;
165 if(!son[s]) return;
166 dfs2(son[s],t);
167 for(int i=head[s];i;i=nex[i]){
168 int v=to[i];
169 if(v!=fa[s]&&v!=son[s]) dfs2(v,v);
170 }
171 }
172 inline int getown(int x){
173 if(col[x]) return x;
174 while(x){
175 if(bl.query(dfn[x])-bl.query(dfn[top[x]]-1)==0){ x=fa[top[x]]; continue; }
176 if(col[x]) return x;
177 int res,l=dfn[top[x]],r=dfn[x];
178 while(l<=r){
179 int mid=l+r>>1;
180 if(bl.query(dfn[x])-bl.query(mid-1)) res=mid, l=mid+1;
181 else r=mid-1;
182 }
183 return id[res];
184 }
185 return 1;
186 }
187 } using namespace Tree_Division;
188
189 signed main(){
190 // freopen("pastel2.in","r",stdin);
191 // freopen("out","w",stdout);
192 n=read(); m=read();
193 for(int i=2;i<=n;i++) add(read(),i);
194 dfs1(1,0); dfs2(1,1); insert(1,1,n,1,siz[1],0); bl.insert(1,1); col[1]=1;
195 while(m--){
196 opt=read(); k=read(); if(opt==2||opt==4) w=read();
197 if(opt==1){
198 int tmp=getown(k);
199 write(queryv(1,1,n,dfn[tmp])+queryc(1,1,n,dfn[k],dfn[k]),'\n');
200 }
201 if(opt==2) update(1,1,n,dfn[k],dfn[k],w);
202 if(opt==3){
203 int res=0;
204 int tmp=getown(k);
205 if(!col[k]) res+=queryv(1,1,n,dfn[tmp])*(siz[k]-queryn(1,1,n,dfn[k],dfn[k]+siz[k]-1));
206 res+=querys(1,1,n,dfn[k],dfn[k]+siz[k]-1)+queryc(1,1,n,dfn[k],dfn[k]+siz[k]-1);
207 write(res,'\n');
208 }
209 if(opt==4) update(1,1,n,dfn[k],dfn[k]+siz[k]-1,w);
210 if(opt==5){
211 int tmp=getown(k),numm=siz[k]-queryn(1,1,n,dfn[k],dfn[k]+siz[k]-1);
212 int vall=queryv(1,1,n,dfn[tmp]);
213 col[k]=1;
214 insert(1,1,n,dfn[k],numm,vall);
215 insert(1,1,n,dfn[tmp],queryn(1,1,n,dfn[tmp],dfn[tmp])-numm,vall);
216 bl.insert(dfn[k],1);
217 }
218 if(opt==6){
219 int size=queryn(1,1,n,dfn[k],dfn[k]);
220 col[k]=0; bl.insert(dfn[k],-1);
221 int tmp=getown(k),ww=queryv(1,1,n,dfn[k])-queryv(1,1,n,dfn[tmp]);
222 insert(1,1,n,dfn[tmp],queryn(1,1,n,dfn[tmp],dfn[tmp])+size,queryv(1,1,n,dfn[tmp]));
223 modify(1,1,n,dfn[k],dfn[k]+siz[k]-1,ww);
224 delet(1,1,n,dfn[k]);
225 update(1,1,n,dfn[k],dfn[k]+siz[k]-1,-ww);
226 }
227 }
228 return 0;
229 }

[NOIP模拟46]鼠树的更多相关文章

  1. 8.23考试总结(NOIP模拟46)[数数·数树·鼠树·ckw的树]

    T1 数数 解题思路 大概是一个签到题的感觉...(但是 pyt 并没有签上) 第一题当然可以找规律,但是咱们还是老老实实搞正解吧... 先从小到大拍个序,这样可以保证 \(a_l<a_r\) ...

  2. Noip模拟46 2021.8.23

    给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...

  3. noip模拟46

    A. 数数 排好序从两头贪心即可 B. 数树 首先很容易想到容斥 如果选择的边集的相关点集有点的度数大于 \(1\) 是不合法的 也就是说一定形成若干条长度不一的链 要给这些链上的点安排排列中的数,方 ...

  4. [考试总结]noip模拟46

    脑袋确实是不好使了需要回家暴颓治疗 数数数树鼠树 真好玩. 数数 大水题一个,妥妥的签到题目,然后... 我没签上 气展了!!! 其实我还是想麻烦了. 就是我们实际上就是排序之后每一次找头上和尾巴上的 ...

  5. NOIP模拟 Work - 二分 + 树状数组 / ???

    题目分析 如果没有最后的注意事项,此题就是二分裸题.有了注意事项,会有两种思路: 在线:二分天数t,并在主席树上求1~t天中大于d(浪费的时间)的时间之和以及数量,答案即为:sum - d * cnt ...

  6. 2018.10.08 NOIP模拟 栅栏(树状数组+rand)

    传送门 今天的送分题. 首先考虑每次给要围上栅栏的矩阵里的整体加上1,如果栅栏被撤销就整体减1,最后比较两个点的值是否相同来进行判断. 然而这样的效果并不理想,很容易卡掉. 进一步思考,我们第iii次 ...

  7. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  8. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  9. 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]

    6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...

随机推荐

  1. vuex前端工程化之动态导入文件--require.context( )

    随着项目的复杂,文件结构越来越多,Store中modules中的文件也越来越多,如果一个一个加载是不是很麻烦呢? 先看一个项目中store项目结构: 过去都是通过import分别引入文件: 1 imp ...

  2. (2)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud是什么?Spring Cloud版本介绍

    ​ Spring Cloud 是一系列框架的有序集合.它利用 Spring Boot 的开发便利性,巧妙地简化了分布式系统基础设施的开发,如服务注册.服务发现.配置中心.消息总线.负载均衡.断路器.数 ...

  3. 【转】shell中的$0 $n $# $* $@ $? $$ 变量 if case for while

    shell中的$0 $n $# $* $@ $? $$  shell 编程 | shift 命令用法笔记 $0当前脚本的文件名 $n传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个 ...

  4. Brute Force暴力破解

    Low 服务器只是验证了参数Login是否被设置,没有任何的防爆破机制,且对参数username.password没有做任何过滤,存在明显的sql注入漏洞. 方法一:bp爆破 直接对爆破密码得到pas ...

  5. VS Code + WSL 搭建 RaspberryPi Pico 开发环境

    前面老周写一堆 .NET 与树莓派相关的水文.其实使用的是.net的 IOT 库,并不只是树莓派,其他运行 Linux 的开发板都适用,只要有 GPIO 就行.老周好像在哪看到过,有 USB 转GPI ...

  6. SpringCloud 学习总结

    SpringCloud 学习总结 学习回顾 1.Maven依赖管理 ​ 在微服务项目中,我们一般是先创建一个父项目模块对整个项目的依赖进行版本限定和依赖控制,子模块继承父模块后,不需要再考虑版本和依赖 ...

  7. PHP设计模式之命令模式

    命令模式,也称为动作或者事务模式,很多教材会用饭馆来举例.作为顾客的我们是命令的下达者,服务员是这个命令的接收者,菜单是这个实际的命令,而厨师是这个命令的执行者.那么,这个模式解决了什么呢?当你要修改 ...

  8. 微信小程序函数间传递url的参数丢失问题

    可以使用encodeURIComponent():函数可把字符串作为 URI 组件进行编码. 可以使用decodeURIComponent():函数可把字符串作为 URI 组件进行解码.  

  9. requests + 正则表达式 获取 ‘猫眼电影top100’。

    使用 进程池Pool 提高爬取数据的速度. 1 # !/usr/bin/python 2 # -*- coding:utf-8 -*- 3 import requests 4 from request ...

  10. 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07

    百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...