传送门

解题思路:

算是补坑了,这题除了Invert以外就可以树剖线段树解决了。

考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈。

最暴力的方法是暴力交换权值,然而这种方法忽略了当前树链剖分序的一个性质,那就是很多部分的树链是连续的,而且仅有$O(\lg n)$个区间。

考虑只有一个区间的做法,就很显然是区间翻转(这个不会搞的话你是怎么做到这道题的),于是,由于区间个数并不多,我们大胆猜想:正确的解法就是考虑翻如何转这些不连续区间

由于链区间具有一定的连续性,且我们需要翻转其权值,考虑更换我们所使用的数据结构,Splay和FHQ Treap都可以,我个人更倾向于使用后者(因为好写)。

现在问题瓶颈就是如何翻转不连续的区间权值。

其实方法很简单,将这$O(\lg n)$个拼接在一起,翻转,再重新安回去,很显然这样做的时间复杂度是$O((\lg n)^2))$的。

考虑具体的操作,由于下标索引在拆树的时候可能改变非常恶心,所以我们预处理出x-y中所有链区间,按dfs序排序,倒着拆,把x到lca上的树链翻转后拼接,再与y到lca上的树链翻转。最后再翻转,正着安回去。

大概就可以愉快地AC了。

代码:

  1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<algorithm>
5 #define lll tr[spc].ls
6 #define rrr tr[spc].rs
7 typedef long long lnt;
8 struct chain{
9 int ind;
10 int len;
11 bool x;
12 }ch[100010];
13 struct trnt{
14 int ls,rs;
15 int lzt;
16 int wgt;
17 int rnd;
18 lnt lzta;
19 lnt val;
20 lnt sum;
21 lnt maxval,minval;
22 void rediff(int seed){
23 ls=rs=lzt=0;
24 lzta=val=sum=maxval=minval=0;
25 rnd=seed+rand()%500+1;
26 wgt=1;
27 return ;
28 }
29 }tr[1000010];
30 struct pnt{
31 int hd;
32 int fa;
33 int tp;
34 int dep;
35 int ind;
36 int mxs;
37 int wgt;
38 }p[100010];
39 struct ent{
40 int twd;
41 int lst;
42 }e[100010];
43 int cnt;
44 int siz;
45 int dfn;
46 int top;
47 int n,m,r;
48 char cmd[100];
49 int rootl,rootr,rootm,root;
50 int pos[100010],size[100010];
51 int cmp(chain a,chain b){
52 return a.ind<b.ind;
53 }
54 void ade(int f,int t){
55 cnt++;
56 e[cnt].twd=t;
57 e[cnt].lst=p[f].hd;
58 p[f].hd=cnt;
59 return ;
60 }
61 void push_up(int spc){
62 tr[spc].wgt=1;
63 tr[spc].minval=tr[spc].maxval=tr[spc].sum=tr[spc].val;
64 if(lll){
65 tr[spc].wgt+=tr[lll].wgt;
66 tr[spc].sum+=tr[lll].sum;
67 tr[spc].minval=std::min(tr[spc].minval,tr[lll].minval);
68 tr[spc].maxval=std::max(tr[spc].maxval,tr[lll].maxval);
69 }
70 if(rrr){
71 tr[spc].wgt+=tr[rrr].wgt;
72 tr[spc].sum+=tr[rrr].sum;
73 tr[spc].minval=std::min(tr[spc].minval,tr[rrr].minval);
74 tr[spc].maxval=std::max(tr[spc].maxval,tr[rrr].maxval);
75 }
76 return ;
77 }
78 void add(int spc,lnt val){
79 if(!spc){
80 return ;
81 }
82 tr[spc].val+=val;
83 tr[spc].lzta+=val;
84 tr[spc].maxval+=val;
85 tr[spc].minval+=val;
86 tr[spc].sum+=val*tr[spc].wgt;
87 return ;
88 }
89 void trr(int spc){
90 if(!spc){
91 return ;
92 }
93 std::swap(lll,rrr);
94 tr[spc].lzt^=1;
95 return ;
96 }
97 void push_down(int spc){
98 if(tr[spc].lzt){
99 trr(lll);
100 trr(rrr);
101 tr[spc].lzt=0;
102 }
103 if(tr[spc].lzta){
104 add(lll,tr[spc].lzta);
105 add(rrr,tr[spc].lzta);
106 tr[spc].lzta=0;
107 }
108 return ;
109 }
110 void build(int l,int r,int &spc,int seed){
111 if(l>r){
112 return ;
113 }
114 int mid=(l+r)>>1;
115 spc=++siz;
116 tr[spc].rediff(seed);
117 build(l,mid-1,lll,tr[spc].rnd);
118 build(mid+1,r,rrr,tr[spc].rnd);
119 push_up(spc);
120 return ;
121 }
122 void split(int spc,int &ll,int &rr,int k){
123 if(!spc){
124 ll=rr=0;
125 return ;
126 }
127 push_down(spc);
128 if(tr[lll].wgt<k){
129 ll=spc;
130 split(rrr,rrr,rr,k-tr[lll].wgt-1);
131 }else{
132 rr=spc;
133 split(lll,ll,lll,k);
134 }
135 push_up(spc);
136 return ;
137 }
138 int merge(int ll,int rr){
139 if(!ll||!rr){
140 return ll|rr;
141 }else{
142 if(tr[ll].rnd<tr[rr].rnd){
143 push_down(ll);
144 tr[ll].rs=merge(tr[ll].rs,rr);
145 push_up(ll);
146 return ll;
147 }else{
148 push_down(rr);
149 tr[rr].ls=merge(ll,tr[rr].ls);
150 push_up(rr);
151 return rr;
152 }
153 }
154 return 0;
155 }
156 void Basic_dfs(int x,int f){
157 p[x].fa=f;
158 p[x].wgt=1;
159 p[x].dep=p[f].dep+1;
160 int maxs(-1);
161 for(int i=p[x].hd;i;i=e[i].lst){
162 int to=e[i].twd;
163 if(to==f){
164 continue;
165 }
166 Basic_dfs(to,x);
167 p[x].wgt+=p[to].wgt;
168 if(p[to].wgt>maxs){
169 p[x].mxs=to;
170 maxs=p[to].wgt;
171 }
172 }
173 return ;
174 }
175 void Build_dfs(int x,int t){
176 if(!x){
177 return ;
178 }
179 p[x].tp=t;
180 p[x].ind=++dfn;
181 Build_dfs(p[x].mxs,t);
182 for(int i=p[x].hd;i;i=e[i].lst){
183 int to=e[i].twd;
184 if(p[to].ind){
185 continue;
186 }
187 Build_dfs(to,to);
188 }
189 return ;
190 }
191 void Increase(int x,int y,lnt z){
192 while(p[x].tp!=p[y].tp){
193 if(p[p[x].tp].dep<p[p[y].tp].dep){
194 std::swap(x,y);
195 }
196 int S(p[p[x].tp].ind-1),T(p[x].ind);
197 split(root,rootl,rootr,T);
198 split(rootl,rootl,rootm,S);
199 add(rootm,z);
200 root=merge(rootl,merge(rootm,rootr));
201 x=p[p[x].tp].fa;
202
203 }
204 if(p[x].dep>p[y].dep){
205 std::swap(x,y);
206 }
207 int S(p[x].ind-1),T(p[y].ind);
208 split(root,rootl,rootr,T);
209 split(rootl,rootl,rootm,S);
210 add(rootm,z);
211 root=merge(rootl,merge(rootm,rootr));
212 return ;
213 }
214 void Invert(int x,int y){
215 top=0;
216 if(p[x].ind>p[y].ind){
217 std::swap(x,y);
218 }
219 int lca(r);
220 int tmpx(x),tmpy(y);
221 while(p[x].tp!=p[y].tp){
222 if(p[p[x].tp].dep>p[p[y].tp].dep){
223 top++;
224 ch[top].ind=p[p[x].tp].ind;
225 ch[top].len=p[x].ind-p[p[x].tp].ind+1;
226 ch[top].x=true;
227 x=p[p[x].tp].fa;
228 }else{
229 top++;
230 ch[top].ind=p[p[y].tp].ind;
231 ch[top].len=p[y].ind-p[p[y].tp].ind+1;
232 ch[top].x=false;
233 y=p[p[y].tp].fa;
234 }
235 }
236 if(p[x].dep<=p[y].dep){
237 top++;
238 ch[top].ind=p[x].ind;
239 ch[top].len=p[y].ind-p[x].ind+1;
240 ch[top].x=false;
241 }else{
242 top++;
243 ch[top].ind=p[y].ind;
244 ch[top].len=p[x].ind-p[y].ind+1;
245 ch[top].x=true;
246 }
247 std::sort(ch+1,ch+top+1,cmp);
248 int tmptop(top);
249 int root_(0);
250 while(top){
251 int S(ch[top].ind-1),T(ch[top].ind+ch[top].len-1);
252 split(root,rootl,rootr,T);
253 split(rootl,rootl,rootm,S);
254 root=merge(rootl,rootr);
255 if(ch[top].x){
256 trr(rootm);
257 }
258 root_=merge(rootm,root_);
259 top--;
260 }
261 trr(root_);
262 top=1;
263 while(top<=tmptop){
264 int S(ch[top].ind-1);
265 split(root,rootl,rootr,S);
266 split(root_,rootm,root_,ch[top].len);
267 if(ch[top].x){
268 trr(rootm);
269 }
270 root=merge(rootl,merge(rootm,rootr));
271 top++;
272 }
273 return ;
274 }
275 lnt Sum(int x,int y){
276 lnt ans(0);
277 while(p[x].tp!=p[y].tp){
278 if(p[p[x].tp].dep<p[p[y].tp].dep){
279 std::swap(x,y);
280 }
281 int S(p[p[x].tp].ind-1),T(p[x].ind);
282 split(root,rootl,rootr,T);
283 split(rootl,rootl,rootm,S);
284 ans=ans+tr[rootm].sum;
285 root=merge(rootl,merge(rootm,rootr));
286 x=p[p[x].tp].fa;
287 }
288 if(p[x].dep>p[y].dep){
289 std::swap(x,y);
290 }
291 int S(p[x].ind-1),T(p[y].ind);
292 split(root,rootl,rootr,T);
293 split(rootl,rootl,rootm,S);
294 ans=ans+tr[rootm].sum;
295 root=merge(rootl,merge(rootm,rootr));
296 return ans;
297 }
298 lnt Major(int x,int y){
299 lnt ans(-0x3f3f3f3f3f3fll);
300 while(p[x].tp!=p[y].tp){
301 if(p[p[x].tp].dep<p[p[y].tp].dep){
302 std::swap(x,y);
303 }
304 int S(p[p[x].tp].ind-1),T(p[x].ind);
305 split(root,rootl,rootr,T);
306 split(rootl,rootl,rootm,S);
307 ans=std::max(ans,tr[rootm].maxval);
308 root=merge(rootl,merge(rootm,rootr));
309 x=p[p[x].tp].fa;
310 }
311 if(p[x].dep>p[y].dep){
312 std::swap(x,y);
313 }
314 int S(p[x].ind-1),T(p[y].ind);
315 split(root,rootl,rootr,T);
316 split(rootl,rootl,rootm,S);
317 ans=std::max(ans,tr[rootm].maxval);
318 root=merge(rootl,merge(rootm,rootr));
319 return ans;
320 }
321 lnt Minor(int x,int y){
322 lnt ans(0x3f3f3f3f3f3fll);
323 while(p[x].tp!=p[y].tp){
324 if(p[p[x].tp].dep<p[p[y].tp].dep){
325 std::swap(x,y);
326 }
327 int S(p[p[x].tp].ind-1),T(p[x].ind);
328 split(root,rootl,rootr,T);
329 split(rootl,rootl,rootm,S);
330 ans=std::min(ans,tr[rootm].minval);
331 root=merge(rootl,merge(rootm,rootr));
332 x=p[p[x].tp].fa;
333 }
334 if(p[x].dep>p[y].dep){
335 std::swap(x,y);
336 }
337 int S(p[x].ind-1),T(p[y].ind);
338 split(root,rootl,rootr,T);
339 split(rootl,rootl,rootm,S);
340 ans=std::min(ans,tr[rootm].minval);
341 root=merge(rootl,merge(rootm,rootr));
342 return ans;
343 }
344 void pia(int spc){
345 if(!spc){
346 return ;
347 }
348 push_down(spc);
349 pia(lll);
350 printf("%lld ",tr[spc].val);
351 pia(rrr);
352 return ;
353 }
354 int main(){
355 scanf("%d%d%d",&n,&m,&r);
356 for(int i=1;i<=n;++i){
357 int a,b;
358 scanf("%d%d",&a,&b);
359 ade(a,b);
360 ade(b,a);
361 }
362 build(1,n,root,0);
363 Basic_dfs(r,r);
364 Build_dfs(r,r);
365 int pro(0);
366 while(m--){
367 int x,y,z;
368 scanf("%s",cmd+1);
369 if(cmd[1]=='I'){
370 if(cmd[3]=='c'){
371 scanf("%d%d%d",&x,&y,&z);
372 Increase(x,y,lnt(z));
373 }
374 if(cmd[3]=='v'){
375 scanf("%d%d",&x,&y);
376 Invert(x,y);
377 }
378 }
379 if(cmd[1]=='S'){
380 scanf("%d%d",&x,&y);
381 printf("%lld\n",Sum(x,y));
382 }
383 if(cmd[1]=='M'){
384 if(cmd[2]=='a'){
385 scanf("%d%d",&x,&y);
386 printf("%lld\n",Major(x,y));
387 }
388 if(cmd[2]=='i'){
389 scanf("%d%d",&x,&y);
390 printf("%lld\n",Minor(x,y));
391 }
392 }
393 }
394 return 0;
395 }

最新文章

  1. 【转】oracle in和exists、not in和not exists原理和性能探究
  2. CentOS7:安装Puppet
  3. CAD二次开发
  4. 在Android上模拟登录广工正方教务系统查询成绩
  5. 关于scope_identity()与 @@IDENTITY
  6. launch failed.Binary not found
  7. python2.x urllib2和urllib的使用
  8. Docker 执行nginx以及简单进入container
  9. POJ3181--Dollar Dayz(动态规划)
  10. Testing - 软件测试知识梳理 - 软件可靠性测试
  11. text/html &amp; text/plain的区别
  12. mysql错误日志与通用日志
  13. DNS服务器原理介绍(一)
  14. Kali更新deb源
  15. 巨蟒python全栈开发-第11阶段 devops-git入门1
  16. IBatis Map时间参数文字格式不匹配!
  17. MyBatis 插入数据库返回主键
  18. ms project展开和折叠任务
  19. [转]WinForm下Splash(启动画面)制作
  20. 非常好!!!Linux源代码阅读——内核引导【转】

热门文章

  1. Solution -「Gym 102759I」Query On A Tree 17
  2. ELK(Elasticsearch 、 Logstash以及Kibana)
  3. nginx 配置ssl证书
  4. HBase学习记录-API
  5. 单片机中volatile的应用
  6. 【C# Task】 ValueTask/Task&lt;TResult&gt;
  7. C#操作WMI指南
  8. Oracle分析函数/排名函数/位移函数/同比环比
  9. LayUI使用注意
  10. html页面引用script出现中文乱码问题