1103: 插线板

时间限制: 1 Sec  内存限制: 128 MB
提交: 14  解决: 7

题目描述

从前有一堆古老的插线板,任意两个插线板之间只有一根导线相连,最终形成一个树状结构。我们假设电线的电阻可以忽略。由于年代久远,插线板的状况不容乐观。每个插线板都对电流有一定的影响,用一个整数表示,若为正,表示对电流起到稳定作用,越大越稳定,若为负,代表对电流产生不好的影响。插线板在连接后。这种影响会叠加,比如a和b连接,a的影响为-1,b为3,则a到b的影响为2。现在提供操作1和2,操作1表示求出插线板a到插线板b之间对电流影响最为乐观的一段的影响数值。(注:数据有问题,这一段元素可以为空)即将a到b的这条“链”取出,形成一个关于影响的序列,这个序列的最大子段和。操作2表示将a到b的链上所有插线板对电流的影响改为一个数值(包括a和b)。现给出插线板的初始状况,请按照要求进行操作,输出结果。

输入

单组测试数据

第一行为插线板个数n。

第二行为插线板1到n初始状态对电流的影响数值。(数值绝对值不超过10000)

第三行开始有n-1行,每行两个数a和b,表示a、b有电线连接,保证形成一棵树。

之后一行有一个正整数m,代表操作个数。

最后m行,每行第一个数为1或2,代表操作种类,若为1,后面跟随两个数l和r,代表求出l和r之间的最好影响数值。若为2,后面跟随三个数l、r和c,代表修改l到r的插线板的影响为c。

输出

对每个操作1输出一个整数,代表最好影响数值,每个输出用一个空格隔开。

样例输入

5
-3 -2 1 2 3
1 2
2 3
1 4
4 5
3
1 2 5
2 3 4 2
1 2 5

样例输出

5 9

提示

n,m<=100000

来源

图论专题


emm这题卡了我好久。。。

由于我校oj的数据贼弱。。暴力就可以过,甚至比我写的o(log(n)^2*n)还快。

暴力的做法就是对于题目所说的点求最近公共祖先(Tarjan+并查集,欧拉序列+st,求2^k的祖先然后不断向上找公共祖先),然后修改的时候把所有点逐个修改,求值的时候把所有点拿出来,求前缀和,维护最小值搞一下就好了。

学长的博客链接做法:http://www.cnblogs.com/neopenx/p/4503066.html ,暴力法。

  1. #include "cstdio"
  2. #include "cstring"
  3. #include "vector"
  4. #include "algorithm"
  5. using namespace std;
  6. #define maxn 100005
  7. #define inf 0x3f3f3f3f
  8. int head[maxn],qhead[maxn],lag[maxn],kth[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn],p[maxn],s1[maxn],s2[maxn];
  9. bool isUpdate[maxn];
  10. struct Edge
  11. {
  12. int to,next;
  13. }e[maxn*];
  14. struct Query
  15. {
  16. int from,to,next,idx,c;
  17. }q[maxn*];
  18. void addedge(int u,int v)
  19. {
  20. e[tot1].to=v;
  21. e[tot1].next=head[u];
  22. head[u]=tot1++;
  23. }
  24. void addquery(int u,int v,int idx,int c=inf)
  25. {
  26. q[tot2].from=u;
  27. q[tot2].to=v;
  28. q[tot2].next=qhead[u];
  29. q[tot2].idx=idx;
  30. if(c!=inf) q[tot2].c=c;
  31. qhead[u]=tot2++;
  32. }
  33. int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
  34. void Union(int u,int v)
  35. {
  36. u=find(u),v=find(v);
  37. if(u!=v) f[v]=u;
  38. }
  39. void LCA(int u)
  40. {
  41. vis[u]=true;
  42. f[u]=u;
  43. for(int i=head[u];i!=-;i=e[i].next)
  44. {
  45. int v=e[i].to;
  46. if(!vis[v])
  47. {
  48. p[v]=u;
  49. LCA(v);
  50. Union(u,v);
  51. }
  52. }
  53. for(int i=qhead[u];i!=-;i=q[i].next)
  54. {
  55. int v=q[i].to;
  56. if(vis[v]) ancestor[q[i].idx]=find(v);
  57. //or storage e[i].lca=e[i^1].lca=find(v)
  58. }
  59. }
  60. int sum(int num)
  61. {
  62. s2[]=s1[];
  63. int Max=,Min=;
  64. for(int i=; i<num; i++)
  65. s2[i]=s2[i-]+s1[i];
  66. for(int i=;i<num;i++)
  67. {
  68. Min=min(Min,s2[i]);
  69. Max=max(Max,s2[i]-Min);
  70. }
  71. return Max;
  72. }
  73. int main()
  74. {
  75. //freopen("in.txt","r",stdin);
  76. int T,n,m,u,v,c,cmd,qcnt=;
  77. scanf("%d",&n);
  78. tot1=tot2=;
  79. memset(head,-,sizeof(head));
  80. memset(qhead,-,sizeof(qhead));
  81. memset(vis,,sizeof(vis));
  82. memset(isUpdate,,sizeof(isUpdate));
  83. for(int i=;i<=n;i++) scanf("%d",&lag[i]);
  84. for(int i=; i<n-; i++)
  85. {
  86. scanf("%d%d",&u,&v);
  87. addedge(u,v);
  88. addedge(v,u);
  89. }
  90. scanf("%d",&m);
  91. for(int i=; i<m; i++)
  92. {
  93. scanf("%d",&cmd);
  94. if(cmd==)
  95. {
  96. scanf("%d%d%d",&u,&v,&c);
  97. addquery(u,v,i,c);
  98. addquery(v,u,i,c);
  99. isUpdate[i]=true;
  100. }
  101. else
  102. {
  103. scanf("%d%d",&u,&v);
  104. addquery(u,v,i);
  105. addquery(v,u,i);
  106. }
  107. }
  108. LCA();
  109. vector<int> ans;
  110. for(int i=; i<tot2; i=i+)
  111. {
  112. int u=q[i].from,v=q[i].to,idx=q[i].idx;
  113. int ed=ancestor[idx],cnt=;
  114. if(isUpdate[qcnt])
  115. {
  116. int c=q[i].c;
  117. while(u!=ed) lag[u]=c,u=p[u];
  118. lag[ed]=c;
  119. while(v!=ed) lag[v]=c,v=p[v];
  120. }
  121. else
  122. {
  123. while(u!=ed) s1[cnt++]=lag[u],u=p[u];
  124. s1[cnt++]=lag[ed];
  125. vector<int> rev;
  126. while(v!=ed) rev.push_back(lag[v]),v=p[v];
  127. for(int j=rev.size()-; j>=; j--) s1[cnt++]=rev[j];
  128. int x=sum(cnt);
  129. ans.push_back(x);
  130. }
  131. qcnt++;
  132. }
  133. for(int i=;i<ans.size()-;i++) printf("%d ",ans[i]);
  134. printf("%d\n",ans[ans.size()-]);
  135. }

然后我的做法是经典的线段树求区间最大子段和的做法,维护包含区间左端点的最大值lt,右端点的最大值rt,区间内最大值in,以及区间总和all。但是题目给的是一棵树,我们把它树链刨分以后再把一段一段地求前述四个值并合并。然后找到合并后的最大值即为答案。

  1. #include<bits/stdc++.h>
  2. #define clr(x) memset(x,0,sizeof(x))
  3. #define clr_1(x) memset(x,-1,sizeof(x))
  4. #define INF 0x3f3f3f3f
  5. #define mod 1000000007
  6. #define LL long long
  7. using namespace std;
  8. const int N=1e4+;
  9. struct edg
  10. {
  11. int next,to;
  12. }edge[N<<];
  13. int head[N],etot;
  14. void addedge(int u,int v)
  15. {
  16. edge[++etot]=(edg){head[u],v};
  17. head[u]=etot;
  18. return ;
  19. }
  20. int fro[N],bac[N],dep[N],fa[N],val[N],top[N],clk,tsize[N],son[N],dfn[N];
  21. struct node
  22. {
  23. int l,r,tag,lt,rt,in,all;
  24. }tree[N<<];
  25. int n,m,k,u,v,c,op;
  26. void init()
  27. {
  28. etot=;
  29. clk=;
  30. clr_1(head);
  31. dep[]=;
  32. fa[]=;
  33. return ;
  34. }
  35. void dfs1(int u)
  36. {
  37. top[u]=u;
  38. tsize[u]=;
  39. son[u]=;
  40. int p;
  41. for(int i=head[u];i!=-;i=edge[i].next)
  42. {
  43. p=edge[i].to;
  44. if(p!=fa[u])
  45. {
  46. fa[p]=u;
  47. dep[p]=dep[u]+;
  48. dfs1(p);
  49. tsize[u]+=tsize[p];
  50. if(!son[u] || tsize[p]>tsize[son[u]] )
  51. son[u]=p;
  52. }
  53. }
  54. return ;
  55. }
  56. void dfs2(int u)
  57. {
  58. fro[u]=++clk;
  59. dfn[clk]=u;
  60. int p;
  61. if(son[u])
  62. {
  63. top[son[u]]=top[u];
  64. dfs2(son[u]);
  65. }
  66. for(int i=head[u];i!=-;i=edge[i].next)
  67. {
  68. p=edge[i].to;
  69. if(p!=fa[u] && p!=son[u])
  70. dfs2(p);
  71. }
  72. bac[u]=clk;
  73. return ;
  74. }
  75. void pushup(int i)
  76. {
  77. tree[i].all=tree[i<<].all+tree[i<<|].all;
  78. tree[i].lt=max(max(tree[i<<].lt,tree[i<<].all+tree[i<<|].lt),tree[i].all);
  79. tree[i].rt=max(max(tree[i<<|].rt,tree[i<<|].all+tree[i<<].rt),tree[i].all);
  80. tree[i].in=max(max(tree[i<<].in,tree[i<<|].in),tree[i<<].rt+tree[i<<|].lt);
  81. return ;
  82. }
  83. void pushdown(int i)
  84. {
  85. if(tree[i].tag!=INF)
  86. {
  87. if(tree[i].l!=tree[i].r)
  88. {
  89. tree[i<<].tag=tree[i].tag;
  90. tree[i<<].all=(tree[i<<].r-tree[i<<].l+)*tree[i<<].tag;
  91. tree[i<<].lt=tree[i<<].rt=tree[i<<].in=(tree[i<<].tag>=?tree[i<<].all:tree[i<<].tag);
  92. tree[i<<|].tag=tree[i].tag;
  93. tree[i<<|].all=(tree[i<<|].r-tree[i<<|].l+)*tree[i<<|].tag;
  94. tree[i<<|].lt=tree[i<<|].rt=tree[i<<|].in=(tree[i<<|].tag>=?tree[i<<|].all:tree[i<<|].tag);
  95. }
  96. tree[i].tag=INF;
  97. }
  98. return ;
  99. }
  100. void init(int i,int l,int r)
  101. {
  102. tree[i]=(node){l,r,INF};
  103. if(l==r)
  104. {
  105. tree[i].lt=tree[i].rt=tree[i].in=tree[i].all=val[dfn[l]];
  106. return ;
  107. }
  108. int mid=(l+r)>>;
  109. init(i<<,l,mid);
  110. init(i<<|,mid+,r);
  111. pushup(i);
  112. return ;
  113. }
  114. void update(int i,int l,int r,int c)
  115. {
  116. if(tree[i].l>=l && tree[i].r<=r)
  117. {
  118. tree[i].all=(tree[i].r-tree[i].l+)*c;
  119. tree[i].lt=tree[i].rt=tree[i].in=(c>=?tree[i].all:c);
  120. tree[i].tag=c;
  121. return ;
  122. }
  123. pushdown(i);
  124. int mid=(tree[i].l+tree[i].r)>>;
  125. if(l<=mid)
  126. update(i<<,l,r,c);
  127. if(r>mid)
  128. update(i<<|,l,r,c);
  129. pushup(i);
  130. return ;
  131. }
  132. node query(int i,int l,int r)
  133. {
  134. if(tree[i].l>=l && tree[i].r<=r)
  135. return tree[i];
  136. pushdown(i);
  137. int mid=(tree[i].l+tree[i].r)>>;
  138. if(l>mid)
  139. return query(i<<|,l,r);
  140. else if(r<=mid)
  141. return query(i<<,l,r);
  142. else
  143. {
  144. node tmplt=query(i<<,l,r),tmprt=query(i<<|,l,r);
  145. node tmp;
  146. tmp.all=tmplt.all+tmprt.all;
  147. tmp.lt=max(max(tmplt.lt,tmplt.all+tmprt.lt),tmp.all);
  148. tmp.rt=max(max(tmprt.rt,tmprt.all+tmplt.rt),tmp.all);
  149. tmp.in=max(max(tmplt.in,tmprt.in),tmplt.rt+tmprt.lt);
  150. return tmp;
  151. }
  152. }
  153. void tupdate(int u,int v,int c)
  154. {
  155. int tpu=top[u],tpv=top[v];
  156. while(tpu!=tpv)
  157. {
  158. if(dep[tpu]<dep[tpv])
  159. {
  160. swap(u,v);
  161. swap(tpu,tpv);
  162. }
  163. update(,fro[tpu],fro[u],c);
  164. u=fa[tpu];
  165. tpu=top[u];
  166. }
  167. if(dep[u]<dep[v])
  168. swap(u,v);
  169. update(,fro[v],fro[u],c);
  170. return ;
  171. }
  172. int tquery(int u,int v)
  173. {
  174. int tpu=top[u],tpv=top[v];
  175. node tmp[];
  176. clr(tmp);
  177. bool flag[]={,};
  178. int now=;
  179. node tmpn,tp;
  180. int ans=;
  181. while(tpu!=tpv)
  182. {
  183. if(dep[tpu]<dep[tpv])
  184. {
  185. swap(u,v);
  186. swap(tpu,tpv);
  187. now^=;
  188. }
  189. tmpn=query(,fro[tpu],fro[u]);
  190. if(!flag[now])
  191. {
  192. tmp[now]=tmpn;
  193. flag[now]=;
  194. }
  195. else
  196. {
  197. tp.all=tmp[now].all+tmpn.all;
  198. tp.lt=max(max(tmpn.lt,tmpn.all+tmp[now].lt),tp.all);
  199. tp.rt=max(max(tmp[now].rt,tmp[now].all+tmpn.rt),tp.all);
  200. tp.in=max(max(tmp[now].in,tmpn.in),tmpn.rt+tmp[now].lt);
  201. tmp[now]=tp;
  202. }
  203. u=fa[tpu];
  204. tpu=top[u];
  205. }
  206. if(dep[u]<dep[v])
  207. swap(u,v),now^=;
  208. tmpn=query(,fro[v],fro[u]);
  209. if(flag[now])
  210. {
  211. tp.all=tmp[now].all+tmpn.all;
  212. tp.lt=max(max(tmpn.lt,tmpn.all+tmp[now].lt),tp.all);
  213. tp.rt=max(max(tmp[now].rt,tmp[now].all+tmpn.rt),tp.all);
  214. tp.in=max(max(tmp[now].in,tmpn.in),tmpn.rt+tmp[now].lt);
  215. tmpn=tp;
  216. }
  217. if(flag[now^])
  218. {
  219. tp.in=max(max(tmp[now^].in,tmpn.in),tmpn.lt+tmp[now^].lt);
  220. tmpn=tp;
  221. }
  222. return tmpn.in;
  223. }
  224. int main()
  225. {
  226. init();
  227. scanf("%d",&n);
  228. for(int i=;i<=n;i++)
  229. scanf("%d",&val[i]);
  230. for(int i=;i<=n;i++)
  231. {
  232. scanf("%d%d",&u,&v);
  233. addedge(u,v);
  234. addedge(v,u);
  235. }
  236. dfs1();
  237. dfs2();
  238. init(,,n);
  239. scanf("%d",&m);
  240. bool inf=;
  241. for(int i=;i<=m;i++)
  242. {
  243. scanf("%d",&op);
  244. if(op==)
  245. {
  246. scanf("%d%d",&u,&v);
  247. if(!inf)
  248. {
  249. inf=;
  250. printf("%d",max(tquery(u,v),));
  251. }
  252. else printf(" %d",max(tquery(u,v),));
  253. }
  254. else
  255. {
  256. scanf("%d%d%d",&u,&v,&c);
  257. tupdate(u,v,c);
  258. }
  259. }
  260. printf("\n");
  261. return ;
  262. }

所以。。暴力出奇迹?

xcoj 1103 插线板(树链刨分求最大子段和)的更多相关文章

  1. bzoj 5210(树链刨分下做个dp)

    5210: 最大连通子块和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 211  Solved: 65[Submit][Status][Discus ...

  2. hdu 5452(树链刨分)

    看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西... Minimum Cut Time Limit: 3000/2000 MS (Java/O ...

  3. 树链刨分(class版)

    class版树链剖(刨)分 感谢沙华大佬的赞助 其实没什么太大变化,就是用了几次一顿乱指... CODE: #include<iostream> #include<cstdio> ...

  4. HDU - 3966 树链刨分

    题目传送门 操作就是询问某个点的值, 然后就是对一条路径上的值全部修改. 最基本的树刨题目了. 树刨的思想: 1. 对于每个点找到他的重儿子. void dfs1(int o, int u){ sz[ ...

  5. POJ 2763 Housewife Wind 树链拋分

    一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...

  6. HDU 3966 Aragorn's Story 树链拋分

    一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...

  7. P3565 由简单的树形dp 引入 长链刨分

    这道题感觉不太行 因为自己没想出来. 先说一下暴力吧,取三个点 让两两之间的距离相等怎么做呢,看起来是很复杂的样子的,但是仔细观察发现 答案出自一个点的儿子之间 或者儿子和父亲之间. 暴力枚举三个点然 ...

  8. 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)

      2020/4/30   15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...

  9. hdu 3804树链剖分+离线操作

    /* 树链刨分+离线操作 题意:给你一棵树,和询问x,y 从节点x--节点1的小于等于y的最大值. 解:先建一个空树,将树的边权值从小到大排序,将询问y按从小到大排序 对于每次询问y将小于等于y的边权 ...

随机推荐

  1. NGINX: 反向代理 Nexus

    Nginx 反向代理 nexus 的服务, 一直卡在 Initialize... 解决方式是添加一个 header X-Forwarded-Proto: proxy_set_header X-Forw ...

  2. bootstrap 弹窗 数据清除

    bootstrap modal操作简单易用, //清除弹窗原数据 $("#create_modal").on("hidden.bs.modal", functi ...

  3. 浅谈游戏中BUFF的设计要点

    其实这类帖子并没有多少的设计理论,对于策划的提升和帮助也并不大,原因其实在于其适用性太窄,当我要设计XX象棋的时候,它就滚一边去了. 废话不多说切入正题: 游戏中的BUFF/DEBUFF我们见过很多, ...

  4. 安装FFMpeg CentOS 7

    https://linuxadmin.io/install-ffmpeg-on-centos-7/

  5. python实战===一键刷屏

    #当按键q的时候,自动输入 “大家好!”并回车键发送!from pynput import keyboard from pynput.keyboard import Key, Controller k ...

  6. gnu app url[web][5星]

    http://www.gnu.org/software/software.zh-cn.html http://linux.chinaunix.net/news/2010/12/07/1175310.s ...

  7. Oracle例外定义

    例外名 ORA-XXXXX SQLCODE ACCESS_INTO_NULL ORA-06530 -6530 CASE_NOT_FOUND ORA-06592 -6592 COLLECTION_IS_ ...

  8. linux命令(42):wc命令

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  9. Fel表达式使用过程中需要注意的问题

    精度问题: 我们知道java中直接使用float和double参与的计算都可能会产生精度问题,比如0.1+0.3.1.0-0.9 等.所以一般财务系统,都会使用BigDecimal进行加减乘除. 在调 ...

  10. LeetCode解题报告—— Reverse Linked List II & Restore IP Addresses & Unique Binary Search Trees II

    1. Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass ...