[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 ...
随机推荐
- Vulnhub实战-JIS-CTF_VulnUpload靶机👻
Vulnhub实战-JIS-CTF_VulnUpload靶机 下载地址:http://www.vulnhub.com/entry/jis-ctf-vulnupload,228/ 你可以从上面地址获取靶 ...
- 运用shapefile.js解析Shp文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- Python基础 | 字符串格式化输出及print()函数介绍
在写代码时,我们会经常与字符串打交道,Python中控制字符串格式通常有三种形式,分别是使用str%,str.format(),f-str,用法都差不多,但又有一些细微之差. 一起来看看吧~~~ 一. ...
- 一站式交付体验:云效+Kubernetes
背景 云效依托于阿里巴巴研发效能多年规模化持续交付,赋能云上开发者专为云端用户提供的一站式研发协作平台.Kubernetes,由Google开源的容器集群管理平台,面向运维侧提供自动化的集群和应用管理 ...
- HttpClient.PatchAsJsonAsync - dotnet/runtime 项目贡献小记
TL;DR 迫于 PatchAsJsonAsync 方法缺失,我给 dotnet/runtime 项目贡献了相关的 API,可惜要到 .NET7 才能用上. https://github.com/do ...
- 第三次Scrum Metting
日期:2021年4月27日会议主要内容概述:确定后端和前端接口,前端讨论画图页面,解决两处画图问题 一.进度情况# 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 ...
- 大闸蟹的项目分析——CSDN APP
大闸蟹的软件案例分析 项目 内容 这个作业属于那个课程 班级博客 这个作业的要求在哪里 作业要求 我在这个课程的目标是 学习软件工程的相关知识 这个作业在哪个具体方面帮我实现目标 从多角度分析软件 一 ...
- FastAPI 学习之路(二十八)使用密码和 Bearer 的简单 OAuth2
OAuth2 规定在使用(我们打算用的)「password 流程」时,客户端/用户必须将 username 和 password 字段作为表单数据发送.我们看下在我们应该去如何实现呢. 我们写一个登录 ...
- 2021.9.22考试总结[NOIP模拟59]
T1 柱状图 关于每个点可以作出两条斜率绝对值为\(1\)的直线. 将绝对值拆开,对在\(i\)左边的点\(j\),\(h_i-i=h_j-j\),右边则是把减号换成加号. 把每个点位置为横坐标,高度 ...
- 零基础入门之Linux进程基础
计算机实际上可以做的事情实质上非常简单,比如计算两个数的和,再比如在内存中寻找到某个地址等等.这些最基础的计算机动作被称为指令(instruction).所谓的程序(program),就是这样一系列指 ...