学军NOI训练13 T3 白黑树
2015-06-22 16:27
316 查看
唉,大学军有自己的OJ就是好,无限orz
只有周六的比赛是开放的囧,这场比赛最后因为虚拟机卡住没有及时提交……
否则就能让大家看到我有多弱了……
前两题题解写的很详细,可以自己去看,我来随便扯扯T3好了
题目是这样的:
有一棵以1为根的白黑树,每个节点都是黑色或白色,初始权值是0。维护两个操作:
1.选定一个点a,对于所有黑色的点i,将lca(a,i)的权值加上i; 2.将a号点的颜色反转。
最后求每个点权值
很容易想出这样一个暴力:先考虑1操作,权值增加的点一定是a到根路径上的点
且每个点增加的权值都是自己子树内黑点编号和-路径下一个点的子树内黑点遍和(a增加的就是自己子树内黑点的编号和)
这样不难想到一个用dfs序的O(dlogn)+O(logn)(分别代表两个操作复杂度的做法,d是树的深度)
这样可以跑过深度很小的数据(比如菊花图)
但算法还有很大的优化空间,因为路径上点的操作其实是非常类似的
考虑树链剖分的做法,树链剖分后的复杂度保证是基于这个定理: 任意一点到根的路径所经过的轻边不超过logn
因此,对于操作1经过轻边到达的点以及点a,我们还像之前的做法(子树和-子和)树计算贡献,这样就是O(log^2)
下面考虑重链上的点怎么快速统计,设一段重链为u...p,q...v
当前我们走了一条轻边到了q,进入了一条重链上,则我们要快速处理u...p这一段
任何一个非叶子节点i都在一条重链上,定义重链下一个点叫作重儿子,除此之外点i还延伸出一些轻边,那些轻边延伸到的点我们叫做轻儿子
考虑操作1,在重链上的一点x,如果他的重儿子y及其子树上的黑点会对x产生影响
则操作1的点a一定落在x的轻儿子的子树中,而我们知道,从a这样往上爬,
x一定是通过一条轻边到达的点,根据之前的约定,我们是通过子树直接计算对x的影响的
如果a就是x,那也是通过子树直接计算对x的权值影响的
因此在考虑一段重链u...p上的点x,我们是不用他重儿子的子树对他权值的影响,只要考虑,x的轻儿子子树中的黑点和自身是否是黑点的影响即可:
设w[x]为x轻儿子子树以及自身黑点的编号和,在操作1中,我们只要对一段重链u...p打上+1 tag即可;
相当于每个点x的权值加上了w[x]*tag[x],通过线段树,这样的复杂度也是O(log^2);
如果出现操作2怎么办呢,经过之前的分析就很简单了,我们先维护dfs序的子树和
然后只要顺着a向根走,更新a点以及经过轻边到达的点x(更新w[],计算之前tag带来的影响)就可以了
View Code
只有周六的比赛是开放的囧,这场比赛最后因为虚拟机卡住没有及时提交……
否则就能让大家看到我有多弱了……
前两题题解写的很详细,可以自己去看,我来随便扯扯T3好了
题目是这样的:
有一棵以1为根的白黑树,每个节点都是黑色或白色,初始权值是0。维护两个操作:
1.选定一个点a,对于所有黑色的点i,将lca(a,i)的权值加上i; 2.将a号点的颜色反转。
最后求每个点权值
很容易想出这样一个暴力:先考虑1操作,权值增加的点一定是a到根路径上的点
且每个点增加的权值都是自己子树内黑点编号和-路径下一个点的子树内黑点遍和(a增加的就是自己子树内黑点的编号和)
这样不难想到一个用dfs序的O(dlogn)+O(logn)(分别代表两个操作复杂度的做法,d是树的深度)
这样可以跑过深度很小的数据(比如菊花图)
但算法还有很大的优化空间,因为路径上点的操作其实是非常类似的
考虑树链剖分的做法,树链剖分后的复杂度保证是基于这个定理: 任意一点到根的路径所经过的轻边不超过logn
因此,对于操作1经过轻边到达的点以及点a,我们还像之前的做法(子树和-子和)树计算贡献,这样就是O(log^2)
下面考虑重链上的点怎么快速统计,设一段重链为u...p,q...v
当前我们走了一条轻边到了q,进入了一条重链上,则我们要快速处理u...p这一段
任何一个非叶子节点i都在一条重链上,定义重链下一个点叫作重儿子,除此之外点i还延伸出一些轻边,那些轻边延伸到的点我们叫做轻儿子
考虑操作1,在重链上的一点x,如果他的重儿子y及其子树上的黑点会对x产生影响
则操作1的点a一定落在x的轻儿子的子树中,而我们知道,从a这样往上爬,
x一定是通过一条轻边到达的点,根据之前的约定,我们是通过子树直接计算对x的影响的
如果a就是x,那也是通过子树直接计算对x的权值影响的
因此在考虑一段重链u...p上的点x,我们是不用他重儿子的子树对他权值的影响,只要考虑,x的轻儿子子树中的黑点和自身是否是黑点的影响即可:
设w[x]为x轻儿子子树以及自身黑点的编号和,在操作1中,我们只要对一段重链u...p打上+1 tag即可;
相当于每个点x的权值加上了w[x]*tag[x],通过线段树,这样的复杂度也是O(log^2);
如果出现操作2怎么办呢,经过之前的分析就很简单了,我们先维护dfs序的子树和
然后只要顺着a向根走,更新a点以及经过轻边到达的点x(更新w[],计算之前tag带来的影响)就可以了
1 type node=record 2 po,next:longint; 3 end; 4 5 var e:array[0..400010] of node; 6 top,p,s,fa,d,a,b,c:array[0..200010] of longint; 7 f,w,ans:array[0..200010] of int64; 8 tree:array[0..200010*4] of longint; 9 t,i,n,m,len,x,y:longint; 10 11 function lowbit(x:longint):longint; 12 begin 13 exit(x and (-x)); 14 end; 15 16 procedure add(x,y:longint); 17 begin 18 inc(len); 19 e[len].po:=y; 20 e[len].next:=p[x]; 21 p[x]:=len; 22 end; 23 24 procedure ins(x,w:longint); 25 begin 26 while x<=n do 27 begin 28 f[x]:=f[x]+w; 29 x:=x+lowbit(x); 30 end; 31 end; 32 33 34 procedure dfs1(x:longint); 35 var i,y:longint; 36 begin 37 s[x]:=1; 38 i:=p[x]; 39 while i<>0 do 40 begin 41 y:=e[i].po; 42 if s[y]=0 then 43 begin 44 fa[y]:=x; 45 d[y]:=d[x]+1; 46 dfs1(y); 47 s[x]:=s[x]+s[y]; 48 end; 49 i:=e[i].next; 50 end; 51 end; 52 53 procedure dfs2(x:longint); 54 var i,y,q:longint; 55 begin 56 inc(t); 57 b[x]:=t; 58 a[t]:=x; 59 q:=0; 60 i:=p[x]; 61 while i<>0 do 62 begin 63 y:=e[i].po; 64 if b[y]=0 then 65 if s[y]>s[q] then q:=y; 66 i:=e[i].next; 67 end; 68 if q<>0 then 69 begin 70 top[q]:=top[x]; 71 dfs2(q); 72 end; 73 i:=p[x]; 74 while i<>0 do 75 begin 76 y:=e[i].po; 77 if b[y]=0 then 78 begin 79 top[y]:=y; 80 dfs2(y); 81 end; 82 i:=e[i].next; 83 end; 84 end; 85 86 function ask(x:longint):int64; 87 begin 88 ask:=0; 89 while x>0 do 90 begin 91 ask:=ask+f[x]; 92 x:=x-lowbit(x); 93 end; 94 end; 95 96 procedure push(i:longint); 97 begin 98 if tree[i]<>0 then 99 begin 100 inc(tree[i*2],tree[i]); 101 inc(tree[i*2+1],tree[i]); 102 tree[i]:=0; 103 end; 104 end; 105 106 procedure get(i,l,r,x:longint); 107 var m:longint; 108 begin 109 if l=r then 110 begin 111 inc(ans[a[l]],w[a[l]]*int64(tree[i])); 112 tree[i]:=0; 113 end 114 else begin 115 m:=(l+r) shr 1; 116 push(i); 117 if x<=m then get(i*2,l,m,x) 118 else get(i*2+1,m+1,r,x); 119 end; 120 end; 121 122 procedure tag(i,l,r,x,y:longint); 123 var m:longint; 124 begin 125 if (x<=l) and (y>=r) then 126 inc(tree[i]) 127 else begin 128 m:=(l+r) shr 1; 129 push(i); 130 if x<=m then tag(i*2,l,m,x,y); 131 if y>m then tag(i*2+1,m+1,r,x,y); 132 end; 133 end; 134 135 procedure work(x,z:longint); 136 begin 137 ins(b[x],z); 138 while x<>0 do 139 begin 140 get(1,1,n,b[x]); 141 w[x]:=w[x]+z; 142 x:=fa[top[x]]; 143 end; 144 end; 145 146 procedure calc(x:longint); 147 var y:longint; 148 begin 149 y:=0; 150 while x<>0 do 151 begin 152 inc(ans[x],ask(b[x]+s[x]-1)-ask(b[x]-1)); 153 if y<>0 then 154 dec(ans[x],ask(b[y]+s[y]-1)-ask(b[y]-1)); 155 if x<>top[x] then tag(1,1,n,b[top[x]],b[x]-1); 156 y:=top[x]; 157 x:=fa[y]; 158 end; 159 end; 160 161 begin 162 readln(n,m); 163 for i:=1 to n do 164 read(c[i]); 165 for i:=1 to n-1 do 166 begin 167 readln(x,y); 168 add(x,y); 169 add(y,x); 170 end; 171 dfs1(1); 172 top[1]:=1; 173 dfs2(1); 174 for i:=1 to n do 175 if c[i]=1 then work(i,i); 176 for i:=1 to m do 177 begin 178 readln(x,y); 179 if x=1 then calc(y) 180 else begin 181 if c[y]=1 then work(y,-y) 182 else work(y,y); 183 c[y]:=1-c[y]; 184 end; 185 end; 186 for i:=1 to n do 187 begin 188 get(1,1,n,b[i]); 189 writeln(ans[i]); 190 end; 191 end.
View Code
相关文章推荐
- C#中的多态
- 导出成excel文件
- 指针和结构体
- 生成关键字是1~N的随机二叉查找树的函数
- 如何使用maven建一个web3.0的项目
- 串的模式匹配
- 指针和结构体
- linux 在proc文件系统下创建文件
- redis文档翻译_key设置过期时间
- 数据结构之线索二叉树
- malloc原理和内存碎片
- 《你的灯还亮着吗》2
- 最最基层的ajax交互代码jquery+java之间的json跨域传递以及java的json代码返回
- c,c++,java用户自定义标识符命名规则比较
- Android平滑移动——Scroller类研究
- 身份证相关类
- 后缀数组——倍增算法
- JDK和JRE SE、EE和ME
- 堆和栈的区别
- Python学习 之 包和模块