[NOIP模拟46]鼠树
神仙题。
首先不考虑把黑点变白,发现每个白点的信息与它的归属点是相同的。可以在线段树中只维护黑点的信息,再记录$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]鼠树的更多相关文章
- 8.23考试总结(NOIP模拟46)[数数·数树·鼠树·ckw的树]
T1 数数 解题思路 大概是一个签到题的感觉...(但是 pyt 并没有签上) 第一题当然可以找规律,但是咱们还是老老实实搞正解吧... 先从小到大拍个序,这样可以保证 \(a_l<a_r\) ...
- Noip模拟46 2021.8.23
给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...
- noip模拟46
A. 数数 排好序从两头贪心即可 B. 数树 首先很容易想到容斥 如果选择的边集的相关点集有点的度数大于 \(1\) 是不合法的 也就是说一定形成若干条长度不一的链 要给这些链上的点安排排列中的数,方 ...
- [考试总结]noip模拟46
脑袋确实是不好使了需要回家暴颓治疗 数数数树鼠树 真好玩. 数数 大水题一个,妥妥的签到题目,然后... 我没签上 气展了!!! 其实我还是想麻烦了. 就是我们实际上就是排序之后每一次找头上和尾巴上的 ...
- NOIP模拟 Work - 二分 + 树状数组 / ???
题目分析 如果没有最后的注意事项,此题就是二分裸题.有了注意事项,会有两种思路: 在线:二分天数t,并在主席树上求1~t天中大于d(浪费的时间)的时间之和以及数量,答案即为:sum - d * cnt ...
- 2018.10.08 NOIP模拟 栅栏(树状数组+rand)
传送门 今天的送分题. 首先考虑每次给要围上栅栏的矩阵里的整体加上1,如果栅栏被撤销就整体减1,最后比较两个点的值是否相同来进行判断. 然而这样的效果并不理想,很容易卡掉. 进一步思考,我们第iii次 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]
6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...
随机推荐
- Jmeter系列(15)- 常用断言之大小断言
大小断言 大小断言验证响应数据size大小,它的作用范围有主Sample与子Sample:适用场景,判断附件下载的大小,比如项目安装包 完整响应:全部响应信息 响应头:响应头信息,比如http协议的头 ...
- Java基础系列(14)- JavaDoc生成文档
JavaDoc JavaDoc是一种将注释生成HTML文档的技术,生成的HTML文档类似于Java的API,易读且清晰明了 参数信息 @author 作者名 @version 版本号 @since 指 ...
- Java面向对象系列(14)- 接口的定义与实现
接口 普通类:只有具体实现 抽象类:具体实现和规范(抽象方法)都有 接口:只有规范!约束和实现分离 接口就是规范,定义的是一组规则,体现了现实世界中"如果你是-则必须能-"的思想. ...
- 软件测试从业者必备的Linux命令(完整篇)
观点: 关于Linux,测试从业者,看这篇文章就够了 . 具体,往下看 : 网上关于Linux资料太多.太杂,学习没有重点,特别是对于没有基础的从业者,期望通过那些文档,去自学掌握Linux,可能性太 ...
- javascript wchar_t 宽字符 转化为 ascii字符码数组
String.prototype.charCodeAt String.fromCharCode() String.prototype.toUtfArray = function() { return ...
- python学习1-博客-DB操作类
#学习python,准备写一个博客,第一天:在别人代码基础上写一个数据库操作的db.py1)python代码 #!/usr/bin/env python # -*- coding: UTF-8 -*- ...
- [转载]ssh证书登录
转载链接 前言 本文基于实际Linux管理工作,实例讲解工作中使用ssh证书登录的实际流程,讲解ssh证书登录的配置原理,基于配置原理,解决实际工作中,windows下使用SecureCRT证书登录的 ...
- YbtOJ#631-次短路径【左偏树,最短路】
正题 题目链接:https://www.ybtoj.com.cn/contest/114/problem/1 题目大意 给出\(n\)个点\(m\)条边的一张无向图,对于每个点\(i\)求不经过\(i ...
- 使用jacob调用Windows的com对象,进行word、ppt等转换成ptf、html(二)
富文本转pdf : 注意:simsun.ttc 可以百度下载:http://www.pc6.com/softview/SoftView_100415.html package com.orangecd ...
- R7000 电脑调整亮度
R7000 电脑亮度太亮,想调整亮度,fn+F5,F6 不起作用,需要调整显卡的设置