小白逛公园加强版(park)

题目描述

小新经常陪小白去公园玩,也就是所谓的遛狗啦……在小新家附近有n个公园,这些公园通过一些路径相连,并保证每两个公园之间有且仅有一条通路相连(也就是说这是一棵树),小白早就看花了眼,自己也不清楚该去哪些公园玩了。

小白对每个公园都有一个评价(可正可负),并且它只会让小新做两件事:

1. 询问公园a到公园b路径上最大连续公园的评价和,就是说我们把公园a到公园b路径上的公园(包括a和b)排成一条直线,那么小白希望知道一段连续的公园的评价和最大为多少。

2. 修改公园a到公园b路径上(包括a和b)每个公园的评价值。

小新现在已经处理不了n超过10的情况,因此请你来帮忙……

输入

第一行有一个自然数,表示n

第二行有n个自然数,表示一开始小白对每个公园的评价(评价值的绝对值不超过10000)

下面有n-1行,每行两个数a和b,表示公园a和公园b直接由道路相连

再下面一行有一个自然数,表示m

最后m行,每行第一个数k表示要执行的操作。如果k为1,那么后面有两个自然数a和b,表示询问公园a到公园b路径上(包含a和b)最大的连续公园评价和(如果这条路径上每个公园的评价都为负数,那么最大连续和为0)。如果k为2,那么后面有三个自然数a、b和c,表示把公园a到公园b路径上所有的公园(包括a和b)的评价都修改为c。(c的绝对值不超过10000)

输出

对于每次询问,输出最大连续和。(每行一个)

样例输入

  1. 5
  2. -3 -2 1 2 3
  3. 1 2
  4. 2 3
  5. 1 4
  6. 4 5
  7. 3
  8. 1 2 5
  9. 2 3 4 2
  10. 1 2 5

样例输出

  1. 5
  2. 9

提示

对于30%的数据:n,m <= 100

对于70%的数据:n,m <= 50000

对于100%的数据:n,m <= 100000

solution

先写个树剖,转化为区间问题。

考虑如何求一段区间权值和最大的连续子序列

在线段树中记

lm:从左开始的最大值

rm:从右开始的最大值

x:中间的最大值(包括两边)

sum:和

这样就可以维护了

  1. void wh(int k){
  2. tree[k].lm=max(tree[k*2].lm,tree[k*2].sum+tree[k*2+1].lm);
  3. tree[k].rm=max(tree[k*2+1].rm,tree[k*2+1].sum+tree[k*2].rm);
  4. tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
  5. tree[k].x=max(max(tree[k*2].x,tree[k*2+1].x),tree[k*2].rm+tree[k*2+1].lm);
  6. }
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<cmath>
  7. #define maxn 100005
  8. #define inf 1e9
  9. using namespace std;
  10. int n,m,head[maxn],son[maxn],fa[maxn],size[maxn],top[maxn],deep[maxn];
  11. int dfn[maxn],dy[maxn],sc,t1,t2,tot,w[maxn],op,a,b,c,li,ri,ans;
  12. struct node{
  13. int lm,rm,x,sum,l,r;
  14. int bj;
  15. }tree[maxn*4],ansa,ansb;
  16. struct no{
  17. int v,nex;
  18. }e[maxn*2];
  19. void lj(int t1,int t2){
  20. tot++;e[tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
  21. }
  22. void dfs1(int k,int fath){
  23. fa[k]=fath;deep[k]=deep[fath]+1;
  24. int gp=-1,sz=0;
  25. for(int i=head[k];i;i=e[i].nex){
  26. if(e[i].v!=fath){
  27. dfs1(e[i].v,k);
  28. sz+=size[e[i].v];
  29. if(gp==-1)gp=e[i].v;
  30. if(size[e[i].v]>size[gp])gp=e[i].v;
  31. }
  32. }
  33. size[k]=sz+1;son[k]=gp;
  34. }
  35. void dfs2(int k){
  36. dfn[k]=++sc;dy[sc]=k;
  37. if(son[k]!=-1)top[son[k]]=top[k],dfs2(son[k]);
  38. for(int i=head[k];i;i=e[i].nex){
  39. if(e[i].v!=fa[k]&&e[i].v!=son[k]){
  40. top[e[i].v]=e[i].v;
  41. dfs2(e[i].v);
  42. }
  43. }
  44. }
  45. void wh(int k){
  46. tree[k].lm=max(tree[k*2].lm,tree[k*2].sum+tree[k*2+1].lm);
  47. tree[k].rm=max(tree[k*2+1].rm,tree[k*2+1].sum+tree[k*2].rm);
  48. tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
  49. tree[k].x=max(max(tree[k*2].x,tree[k*2+1].x),tree[k*2].rm+tree[k*2+1].lm);
  50. }
  51. void update(int k,int v){
  52. tree[k].sum=(tree[k].r-tree[k].l+1)*v;
  53. if(tree[k].sum<0)tree[k].x=tree[k].lm=tree[k].rm=0;
  54. else tree[k].x=tree[k].lm=tree[k].rm=tree[k].sum;
  55. }
  56. void build(int k,int L,int R){
  57. tree[k].l=L,tree[k].r=R;tree[k].bj=-inf;
  58. if(L==R){
  59. update(k,w[dy[L]]);
  60. return;
  61. }
  62. int mid=L+R>>1;
  63. build(k*2,L,mid);build(k*2+1,mid+1,R);
  64. wh(k);
  65. }
  66. node hb(node a,node b){
  67. node t;
  68. t.lm=max(a.lm,a.sum+b.lm);
  69. t.rm=max(b.rm,b.sum+a.rm);
  70. t.sum=a.sum+b.sum;
  71. t.x=max(max(a.x,b.x),a.rm+b.lm);
  72. return t;
  73. }
  74. void down(int k){
  75. if(tree[k].bj!=-inf){
  76. tree[k*2].bj=tree[k*2+1].bj=tree[k].bj;
  77. update(k*2,tree[k].bj);
  78. update(k*2+1,tree[k].bj);
  79. tree[k].bj=-inf;
  80. }
  81. }
  82. node ask(int k){
  83. if(tree[k].l>=li&&tree[k].r<=ri){
  84. return tree[k];
  85. }
  86. down(k);
  87. int mid=tree[k].l+tree[k].r>>1;
  88. node now;now.x=-1e9;now.lm=now.rm=now.sum=0;
  89. if(li<=mid)now=ask(k*2);
  90. if(ri>mid)now=hb(now,ask(k*2+1));
  91. return now;
  92. }
  93. void lian(int k){
  94. if(tree[k].l>=li&&tree[k].r<=ri){
  95. update(k,c);tree[k].bj=c;
  96. return;
  97. }
  98. down(k);
  99. int mid=tree[k].l+tree[k].r>>1;
  100. if(li<=mid)lian(k*2);
  101. if(ri>mid)lian(k*2+1);
  102. wh(k);
  103. }
  104. int main()
  105. {
  106. cin>>n;
  107. for(int i=1;i<=n;i++)scanf("%d",&w[i]);
  108. for(int i=1;i<n;i++){
  109. scanf("%d%d",&t1,&t2);
  110. lj(t1,t2);lj(t2,t1);
  111. }
  112. dfs1(1,0);top[1]=1;dfs2(1);
  113. build(1,1,n);
  114. cin>>m;
  115. while(m--){
  116. scanf("%d",&op);
  117. if(op==1){
  118. scanf("%d%d",&a,&b);
  119. t1=top[a],t2=top[b];
  120. ansa.x=-1e9;ansa.lm=ansa.rm=ansa.sum=0;
  121. ansb.x=-1e9;ansb.lm=ansb.rm=ansb.sum=0;
  122. while(t1!=t2){
  123. if(deep[t1]>=deep[t2]){
  124. li=dfn[t1],ri=dfn[a];
  125. ansa=hb(ask(1),ansa);
  126. a=fa[t1];t1=top[a];
  127. }
  128. else {
  129. li=dfn[t2],ri=dfn[b];
  130. ansb=hb(ask(1),ansb);
  131. b=fa[t2];t2=top[b];
  132. }
  133. }
  134. if(deep[a]<deep[b]){
  135. li=dfn[a],ri=dfn[b];
  136. ansb=hb(ask(1),ansb);
  137. }
  138. else {
  139. li=dfn[b],ri=dfn[a];
  140. ansa=hb(ask(1),ansa);
  141. }
  142. ans=max(ansa.x,ansb.x);
  143. ans=max(ans,ansa.lm+ansb.lm);
  144. printf("%d\n",max(ans,0));
  145. }
  146. else{
  147. scanf("%d%d%d",&a,&b,&c);
  148. t1=top[a],t2=top[b];
  149. while(t1!=t2){
  150. if(deep[t1]<deep[t2])swap(t1,t2),swap(a,b);
  151. li=dfn[t1],ri=dfn[a];
  152. lian(1);
  153. a=fa[t1],t1=top[a];
  154. }
  155. if(deep[a]<deep[b])swap(a,b);
  156. li=dfn[b],ri=dfn[a];
  157. lian(1);
  158. }
  159. }
  160. return 0;
  161. }

小白逛公园加强版(park)的更多相关文章

  1. [vijos P1083] 小白逛公园

    不知怎地竟有种错觉此题最近做过= =目测是类似的?那道题貌似是纯动归? 本来今晚想做两道题的,一道是本题,一道是P1653疯狂的方格取数或NOI08 Employee,看看现在的时间目测这个目标又达不 ...

  2. Bzoj 1756: Vijos1083 小白逛公园 线段树

    1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1021  Solved: 326[Submit][Statu ...

  3. BZOJ 1756: Vijos1083 小白逛公园

    题目 1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 856  Solved: 264[Submit][Sta ...

  4. JDOJ-P1260 VIJOS-P1083 小白逛公园

    首先,在这里给大家推荐一个网站,https://neooj.com:8082,这是我母校的网站 言归正传,题目描述 VIJOS-P1083 小白逛公园 Time Limit: 1 Sec  Memor ...

  5. 线段树 || BZOJ1756: Vijos1083 小白逛公园 || P4513 小白逛公园

    题面:小白逛公园 题解: 对于线段树的每个节点除了普通线段树该维护的东西以外,额外维护lsum(与左端点相连的最大连续区间和).rsum(同理)和sum……就行了 代码: #include<cs ...

  6. 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...

  7. vijos1083:小白逛公园

    小白逛公园 描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白就根据公园的 ...

  8. TYVJ1427 小白逛公园

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述     小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个 ...

  9. bzoj1756 Vijos1083 小白逛公园

    Description 小新经常陪小白去公园玩,也就是所谓的遛狗啦-在小新家附近有一条"公园路",路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. ...

随机推荐

  1. python_66_生成器2

    import time def consumer(name): print('%s准备吃包子 '%name) while True: baozi=yield print('包子[%s]来了,被[%s] ...

  2. C#做项目时的一些经验分享

    1.对于公用的类型定义,要单独抽取出来,放到单独的DLL中. 2.通过大量定义interface接口,来提高模块化程度,不同功能之间通过实现接口来面向接口编程. 3.如果项目中存在很多非常相似,但是又 ...

  3. AngularJs学习笔记-表单处理

    表单处理 (1)Angular表单API 1.模板式表单,需引入FormsModule 2.响应式表单,需引入ReactiveFormsModule   (2)模板式表单 在Angular中使用for ...

  4. 【luogu P3608 [USACO17JAN]Balanced Photo平衡的照片】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3608 乍一看很容易想到O(N^2)的暴力. 对于每个H[i]从i~i-1找L[i]再从i+1~n找R[i], ...

  5. tp5依赖注入(自动实例化):解决了像类中的方法传对象的问题

    app\index\Demo1.php namespace app\index\controller; /* 容器与依赖注入的原理 ----------------------------- 1.任何 ...

  6. ATM-db-dnhandler

    import os,jsonfrom conf import settings def select(name): user_path = os.path.join(settings.BASE_DB, ...

  7. 25.VUE学习之-单击和双击事件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. python3 练习题100例 (十二)

    题目十二:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个"水仙花数",因为153 ...

  9. Benelux Algorithm Programming Contest 2014 Final

    // Button Bashing (bfs) 1 #include <iostream> #include <cstdio> #include <cstring> ...

  10. 51nod 1107 斜率小于零连线数量 特调逆序数

    逆序数的神题.... 居然是逆序数 居然用逆序数过的 提示...按照X从小到大排列,之后统计Y的逆序数... 之后,得到的答案就是传说中的解(斜率小于零) #include<bits/stdc+ ...