将询问拆成$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的更多相关文章

  1. Bookshop(一)数据库连接

    连接池配置文件db.properties配置 1.新建一个普通文件->改名为db.properties(后缀)手动添加属性 一般为数据库驱动类.数据库连接地址.用户名.用户密码 driver=c ...

  2. 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 ...

  3. jQuery +ajax +json+实现分页

    正文 首先我们创建一般处理程序,来读取数据库中内容,得到返回值. 创建文件,GetData.ashx. 我这里是用的存储过程,存储过程会再下面粘出来,至于数据只是实例,你们可根据需求自行读取数据 代码 ...

  4. 达梦7的试用 与SQLSERVER的简单技术对比

    达梦7的试用 与SQLSERVER的简单技术对比 达梦数据库公司推出了他们的数据库服务管理平台,可以在该平台使用达梦数据库而无须安装达梦7数据库 地址:http://online.dameng.com ...

  5. [ASP.NET MVC 小牛之路]05 - 使用 Ninject

    在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来 ...

  6. [ASP.NET MVC 小牛之路]06 - 使用 Entity Framework

    在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码中手工造的数据.本文将演示如何在ASP.NET MVC中使用E ...

  7. 微冷的雨ASP.NET MVC之葵花宝典(MVC)

    微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...

  8. spring aop注解配置

    spring aop是面向切面编程,使用了动态代理的技术,这样可以使业务逻辑的代码不掺入其他乱七八糟的代码 可以在切面上实现合法性校验.权限检验.日志记录... spring aop 用的多的有两种配 ...

  9. vs.net Web.csproj.webinfo文件

    使用VS工具打开工程的时候,请直接打开BookShop.sln文件, 请修改WEB/Web.csproj.webinfo文件中的<Web URLPath = "http://local ...

随机推荐

  1. Serverless 在 SaaS 领域的最佳实践

    作者 | 计缘 来源 | Serverless 公众号 随着互联网人口红利逐渐减弱,基于流量的增长已经放缓,互联网行业迫切需要找到一片足以承载自身持续增长的新蓝海,产业互联网正是这一宏大背景下的新趋势 ...

  2. Less-23 preg_replace1

    Less-23: 直接跳到Less-23的原因是,Less-(11~22)均为注入点不为get方式的注入.我先把get型注入写的差不多,再回来整理关于注入点的内容. 核心语句: 查询.报错均有回显. ...

  3. kviy TextInput 触发事件

    from kivy.uix.widget import Widget from kivy.app import App from kivy.lang import Builder Builder.lo ...

  4. airtext初始化(一)

  5. [敏捷软工团队博客]Beta设计和计划

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta设计和计划 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Beta ...

  6. windows下安装dirmap详细教程

    今天安装一下dirmap,纯小白非常详细的安装过程 1.先去下载dirmap 下载地址:https://github.com/H4ckForJob/dirmap 点这个绿色的code,然后再点下面这个 ...

  7. 碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python

    碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python 题目描述 在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多边形的边爬行,请求出这些蚂蚁相撞的概率.(这里的相撞是指存在任意两只 ...

  8. AtCoder Grand Contest 055题解

    我太菜啦!!!md,第一题就把我卡死了...感觉对构造题不会再爱了... A - ABC Identity 先来看这个题吧,题意就是给定你一个字符串,让你将这个字符串最多分成6个子串,使得每个字符都在 ...

  9. Spoj 2878 KNIGHTS - Knights of the Round Table | 双联通分量 二分图判定

    题目链接 考虑建立原图的补图,即如果两个骑士不互相憎恨,就在他们之间连一条无向边. 显而易见的是,如果若干个骑士在同一个点数为奇数的环上时,他们就可以在一起开会.换句话说,如果一个骑士被一个奇环包含, ...

  10. 第01课 OpenGL窗口(2)

    下一段包括了所有的绘图代码.任何您所想在屏幕上显示的东东都将在此段代码中出现.以后的每个教程中我都会在例程的此处增加新的代码.如果您对OpenGL已经有所了解的话,您可以在 glLoadIdentit ...