[hdu6973]Bookshop
将询问拆成$x$到$lca$和$lca$($lca$靠近$y$的儿子)到$y$两部分,分别处理(后者以前者的答案为基础)
两者是类似地,不妨仅考虑前者:用树剖将该询问拆成dfs序上若干个区间,考虑从后往前遍历dfs序(显然即从下到上),若当前位置被覆盖则执行该节点的操作
进一步的,考虑将一个位置上的操作对覆盖其的位置批量处理,即将问题离线并维护一棵平衡树,仍从后往前遍历dfs序,并支持:
1.(在区间右端点时)加入一个数
2.将当前平衡树中大于等于$k$的数都减去$k$
3.(在区间左端点时)删除一个数
前两个容易处理(删除可以将下标定为询问编号),对于第三个,对权值分类讨论:
1.权值在$[0,k)$中的数不需要处理
2.权值在$[k,2k)$中的数,每一个数至多经历$o(\log V)$次此操作即会变为0(之后显然就不会被操作了),将这些数取出后再暴力操作,复杂度为$o(q\log n\log V)$
3.权值在$[2k,\infty)$中的数,打懒标记即可(第2类需要暴力处理因为要考虑与$[0,k)$中的数的排名)
总复杂度即$o(n\log ^{2}n)$,可以通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define pii pair<int,int>
5 #define mp make_pair
6 #define fi first
7 #define se second
8 #define s(p) f[k].ch[p]
9 vector<int>v,va[N],vd[N];
10 vector<pii>v0[N],v1[N];
11 int E,rt,t,n,q,x,y,head[N],a[N],st[N],fa[N],sz[N],mx[N],dep[N],dfn[N],idfn[N],top[N];
12 struct Edge{
13 int nex,to;
14 }edge[N<<1];
15 struct Data{
16 int fa,val,mx,mn,tag,ch[2];
17 }f[N];
18 void add_edge(int x,int y){
19 edge[E].nex=head[x];
20 edge[E].to=y;
21 head[x]=E++;
22 }
23 void dfs1(int k,int f,int s){
24 fa[k]=f,sz[k]=1,mx[k]=0,dep[k]=s;
25 for(int i=head[k];i!=-1;i=edge[i].nex)
26 if (edge[i].to!=f){
27 dfs1(edge[i].to,k,s+1);
28 sz[k]+=sz[edge[i].to];
29 if (sz[mx[k]]<sz[edge[i].to])mx[k]=edge[i].to;
30 }
31 }
32 void dfs2(int k,int fa,int t){
33 dfn[k]=++dfn[0],idfn[dfn[0]]=k,top[k]=t;
34 if (mx[k])dfs2(mx[k],k,t);
35 for(int i=head[k];i!=-1;i=edge[i].nex)
36 if ((edge[i].to!=fa)&&(edge[i].to!=mx[k]))dfs2(edge[i].to,k,edge[i].to);
37 }
38 int check(int k){
39 return f[f[k].fa].ch[1]==k;
40 }
41 bool cmp(int x,int y){
42 return (f[x].val<f[y].val)||(f[x].val==f[y].val)&&(x<y);
43 }
44 void upd(int k,int x){
45 f[k].val+=x,f[k].mx+=x,f[k].mn+=x,f[k].tag+=x;
46 }
47 void up(int k){
48 f[k].mx=max(max(f[s(0)].mx,f[s(1)].mx),f[k].val);
49 f[k].mn=min(min(f[s(0)].mn,f[s(1)].mn),f[k].val);
50 }
51 void down(int k){
52 if (s(0))upd(s(0),f[k].tag);
53 if (s(1))upd(s(1),f[k].tag);
54 f[k].tag=0;
55 }
56 void rotate(int k){
57 int F=f[k].fa,G=f[F].fa,p=check(k);
58 f[k].fa=G;
59 if (G)f[G].ch[check(F)]=k;
60 f[s(p^1)].fa=F,f[F].ch[p]=s(p^1);
61 f[F].fa=k,s(p^1)=F;
62 up(F),up(k);
63 }
64 void clear(int k){
65 for(int i=k;i;i=f[i].fa)st[++st[0]]=i;
66 while (st[0])down(st[st[0]--]);
67 }
68 void splay(int k,int fa){
69 clear(k);
70 for(int i=f[k].fa;i!=fa;i=f[k].fa){
71 if (f[i].fa!=fa){
72 if (check(i)==check(k))rotate(i);
73 else rotate(k);
74 }
75 rotate(k);
76 }
77 if (!fa)rt=k;
78 }
79 void get_val(int k){
80 if (!k)return;
81 v.push_back(k);
82 get_val(s(0));
83 get_val(s(1));
84 }
85 int find_pre(int k,int x){
86 if (!k)return 0;
87 down(k);
88 if (!cmp(k,x))return find_pre(s(0),x);
89 int ans=find_pre(s(1),x);
90 if (ans)return ans;
91 return k;
92 }
93 int find_nex(int k,int x){
94 if (!k)return 0;
95 down(k);
96 if (!cmp(x,k))return find_nex(s(1),x);
97 int ans=find_nex(s(0),x);
98 if (ans)return ans;
99 return k;
100 }
101 void add(int k){
102 clear(k);
103 int l=find_pre(rt,k),r=find_nex(rt,k);
104 if (!l){
105 if (!r)rt=k;
106 else{
107 splay(r,0);
108 f[k].fa=rt,f[rt].ch[0]=k;
109 up(rt);
110 }
111 }
112 else{
113 splay(l,0);
114 if (!r){
115 f[k].fa=rt,f[rt].ch[1]=k;
116 up(rt);
117 }
118 else{
119 splay(r,rt);
120 f[k].fa=f[rt].ch[1],f[f[rt].ch[1]].ch[0]=k;
121 up(f[rt].ch[1]),up(rt);
122 }
123 }
124 }
125 void dec(int k){
126 clear(k);
127 int l=find_pre(rt,k),r=find_nex(rt,k);
128 if (!l){
129 if (!r)rt=0;
130 else{
131 splay(r,0);
132 f[rt].ch[0]=0;
133 up(rt);
134 }
135 }
136 else{
137 splay(l,0);
138 if (!r){
139 f[rt].ch[1]=0;
140 up(rt);
141 }
142 else{
143 splay(r,rt);
144 f[f[rt].ch[1]].ch[0]=0;
145 up(f[rt].ch[1]),up(rt);
146 }
147 }
148 f[k].fa=0;
149 }
150 void update_force(int x,int y,int z){
151 v.clear();
152 f[0].val=x,f[q+1].val=y;
153 int l=find_pre(rt,0),r=find_nex(rt,q+1);
154 if (!l){
155 if (!r)get_val(rt);
156 else{
157 splay(r,0);
158 get_val(f[rt].ch[0]);
159 up(rt);
160 }
161 }
162 else{
163 splay(l,0);
164 if (!r){
165 get_val(f[rt].ch[1]);
166 up(rt);
167 }
168 else{
169 splay(r,rt);
170 get_val(f[f[rt].ch[1]].ch[0]);
171 up(f[rt].ch[1]),up(rt);
172 }
173 }
174 for(int i=0;i<v.size();i++){
175 dec(v[i]);
176 f[v[i]].val+=z;
177 add(v[i]);
178 }
179 }
180 void update_tag(int x,int y,int z){
181 f[0].val=x,f[q+1].val=y;
182 int l=find_pre(rt,0),r=find_nex(rt,q+1);
183 if (!l){
184 if (!r)upd(rt,z);
185 else{
186 splay(r,0);
187 upd(f[rt].ch[0],z);
188 up(rt);
189 }
190 }
191 else{
192 splay(l,0);
193 if (!r){
194 upd(f[rt].ch[1],z);
195 up(rt);
196 }
197 else{
198 splay(r,rt);
199 upd(f[f[rt].ch[1]].ch[0],z);
200 up(f[rt].ch[1]),up(rt);
201 }
202 }
203 }
204 int main(){
205 f[0].mn=0x3f3f3f3f;
206 scanf("%d",&t);
207 while (t--){
208 scanf("%d%d",&n,&q);
209 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
210 E=dfn[0]=0;
211 for(int i=1;i<=n;i++)head[i]=-1;
212 for(int i=1;i<n;i++){
213 scanf("%d%d",&x,&y);
214 add_edge(x,y);
215 add_edge(y,x);
216 }
217 dfs1(1,0,0);
218 dfs2(1,0,1);
219 for(int i=1;i<=q;i++){
220 scanf("%d%d%d",&x,&y,&f[i].val);
221 v0[i].clear(),v1[i].clear();
222 while (top[x]!=top[y]){
223 if (dep[top[x]]>dep[top[y]]){
224 v0[i].push_back(mp(dfn[x],dfn[top[x]]));
225 x=fa[top[x]];
226 }
227 else{
228 v1[i].push_back(mp(dfn[top[y]],dfn[y]));
229 y=fa[top[y]];
230 }
231 }
232 if (dfn[x]>dfn[y])v0[i].push_back(mp(dfn[x],dfn[y]));
233 else v1[i].push_back(mp(dfn[x],dfn[y]));
234 }
235 for(int i=1;i<=n;i++)va[i].clear(),vd[i].clear();
236 for(int i=1;i<=q;i++)
237 for(int j=0;j<v0[i].size();j++){
238 va[v0[i][j].fi].push_back(i);
239 vd[v0[i][j].se].push_back(i);
240 }
241 rt=0;
242 for(int i=1;i<=q;i++){
243 f[i].fa=f[i].tag=f[i].ch[0]=f[i].ch[1]=0;
244 f[i].mx=f[i].mn=f[i].val;
245 }
246 for(int i=n;i;i--){
247 int k=a[idfn[i]];
248 for(int j=0;j<va[i].size();j++)add(va[i][j]);
249 update_force(k,(k<<1)-1,-k);
250 update_tag((k<<1),1e9,-k);
251 for(int j=0;j<vd[i].size();j++)dec(vd[i][j]);
252 }
253 for(int i=1;i<=n;i++)va[i].clear(),vd[i].clear();
254 for(int i=1;i<=q;i++)
255 for(int j=0;j<v1[i].size();j++){
256 va[v1[i][j].fi].push_back(i);
257 vd[v1[i][j].se].push_back(i);
258 }
259 rt=0;
260 for(int i=1;i<=q;i++){
261 f[i].fa=f[i].tag=f[i].ch[0]=f[i].ch[1]=0;
262 f[i].mx=f[i].mn=f[i].val;
263 }
264 for(int i=1;i<=n;i++){
265 int k=a[idfn[i]];
266 for(int j=0;j<va[i].size();j++)add(va[i][j]);
267 update_force(k,(k<<1)-1,-k);
268 update_tag((k<<1),1e9,-k);
269 for(int j=0;j<vd[i].size();j++)dec(vd[i][j]);
270 }
271 for(int i=1;i<=q;i++)printf("%d\n",f[i].val);
272 }
273 return 0;
274 }
[hdu6973]Bookshop的更多相关文章
- Bookshop(一)数据库连接
		
连接池配置文件db.properties配置 1.新建一个普通文件->改名为db.properties(后缀)手动添加属性 一般为数据库驱动类.数据库连接地址.用户名.用户密码 driver=c ...
 - java.lang.ClassCastException: xut.bookshop.entity.User_$$_javassist_3 cannot be cast to javassist.util.proxy.Proxy
		
报错信息 java.lang.ClassCastException: xut.bookshop.entity.User_$$_javassist_3 cannot be cast to javassi ...
 - jQuery +ajax +json+实现分页
		
正文 首先我们创建一般处理程序,来读取数据库中内容,得到返回值. 创建文件,GetData.ashx. 我这里是用的存储过程,存储过程会再下面粘出来,至于数据只是实例,你们可根据需求自行读取数据 代码 ...
 - 达梦7的试用 与SQLSERVER的简单技术对比
		
达梦7的试用 与SQLSERVER的简单技术对比 达梦数据库公司推出了他们的数据库服务管理平台,可以在该平台使用达梦数据库而无须安装达梦7数据库 地址:http://online.dameng.com ...
 - [ASP.NET MVC 小牛之路]05 - 使用 Ninject
		
在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...
 - [ASP.NET MVC 小牛之路]06 - 使用 Entity Framework
		
在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码中手工造的数据.本文将演示如何在ASP.NET MVC中使用E ...
 - 微冷的雨ASP.NET MVC之葵花宝典(MVC)
		
微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...
 - spring aop注解配置
		
spring aop是面向切面编程,使用了动态代理的技术,这样可以使业务逻辑的代码不掺入其他乱七八糟的代码 可以在切面上实现合法性校验.权限检验.日志记录... spring aop 用的多的有两种配 ...
 - vs.net Web.csproj.webinfo文件
		
使用VS工具打开工程的时候,请直接打开BookShop.sln文件, 请修改WEB/Web.csproj.webinfo文件中的<Web URLPath = "http://local ...
 
随机推荐
- 每个男孩的机械梦「GitHub 热点速览 v.21.41」
			
作者:HelloGitHub-小鱼干 机械臂可能在医疗剧中看过,可以用来执行一些精细化的操作,例如:缝合之类的.但这次 Dummy-Robot 让你不仅看看而已,还具备一定的实操性(有一定的动手.经济 ...
 - $\Large{\LaTeX}$ 常用公式
			
$$\Large{\LaTeX}$$: \[\Large{\LaTeX} \] $ $ 表示行内 $$ $$ 表示独立 $\operatorname{lcm}(x)$\(\operatorname{l ...
 - 步行(walk.cpp) noip模拟
			
步行(walk.cpp) [题目描述] 小C喜欢步行,只有缓慢的步行,小C才能沉浸于其中,享受旅途中那些美好的瞬间. 小C来到了一座新的城市生活,这座城市可以看成 \(n\) 个点, \(n−1\) ...
 - C# 提取PDF中的表格
			
本文介绍在C#程序中(附VB.NET代码)提取PDF中的表格的方法,调用Spire.PDF for .NET提供的提取表格的类以及方法等来获取表格单元格中的文本内容:代码内容中涉及到的主要类及方法归纳 ...
 - 初学Python-day11 函数4
			
函数 1.递归函数 自己不断调用自己的过程 2.递归求和 1 def sum(arg): 2 if arg == 1: 3 return 1 4 return arg + sum(arg - 1) 5 ...
 - Java:ConcurrentHashMap类小记-2(JDK7)
			
Java:ConcurrentHashMap类小记-2(JDK7) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentH ...
 - 第四次Scrum Metting
			
日期:2021年4月29日 会议主要内容概述:交代近两日工作,进一步细化上次讨论细节,代码合并. 一.进度情况## 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 ...
 - 函数指针和qsort函数
			
1.函数指针的形式: 函数指针:int (*funcP) (int *a, int *b) 表示定义了一个funcP函数指针,指向了返回值为int类型,参数为int* 和int* 的函数 使用方式: ...
 - 如何系统学习C 语言(上)之 基础篇
			
大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...
 - 摘录:ddr3内存条时序概念
			
本文摘自:内存系列二:深入理解硬件原理 - 知乎 (zhihu.com),感谢作者! 上次虽然解决了小张的问题,却引发了他对内存原理的兴趣.这不他又来找我了,说我还欠他一个解释.这次我们约在一个咖啡馆 ...