Given a tree with N ( N<=100000 ) nodes. Each node has a interger value x_i ( |x_i|<=10000 ).

You have to apply Q ( Q<=100000 ) operations:

1. 1 a b : answer the maximum contiguous sum (maybe empty,will always larger than or equal to 0 ) from the path a->b ( inclusive ).

2. 2 a b c : change all value in the path a->b ( inclusive ) to c.
Input

first line consists one interger N.

next line consists N interger x_i.

next N-1 line , each consists two interger u,v , means that node u and node v are connected

next line consists 1 interger Q.

next Q line : 1 a b or 2 a b c .
Output

For each query, output one line the maximum contiguous sum.
Example

Input:
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

Output:
5

9

GSS系列最后一道题终于攻破

树链剖分可做,不过代码很长,280行.....

酝酿了这么久终于写了,以前一直不敢做,今天觉得是时候了

又认真看了一遍入门http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

用了一个下午的时间把它AC了,觉得很欣慰,竟然是一次AC,幸福来得太突然.....

 const
inf=-maxlongint;
type
node=record
lson,rson,left,right,lmax,rmax,amax,lazy,sum:longint;
end; var
tree:array[..]of node;
first,next,last:array[..]of longint;
son,fa,size,dep,w,top,root,a:array[..]of longint;
flag:array[..]of boolean;
tot,n,num,ll,rr:longint; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; procedure swap(var x,y:longint);
var
t:longint;
begin
t:=x;x:=y;y:=t;
end; procedure insert(x,y:longint);
begin
inc(num);
last[num]:=y;
next[num]:=first[x];
first[x]:=num;
end; procedure dfs1(x,d,f:longint);
var
i,j:longint;
begin
fa[x]:=f;
flag[x]:=true;
dep[x]:=d;
size[x]:=;
i:=first[x];
j:=;
while i<> do
begin
if flag[last[i]]=false then
begin
dfs1(last[i],d+,x);
inc(size[x],size[last[i]]);
if size[last[i]]>size[j] then j:=last[i];
end;
i:=next[i];
end;
son[x]:=j;
end; procedure build(l,r:longint);
var
now,mid:longint;
begin
inc(tot);
now:=tot;
with tree[now] do
begin
left:=l;
right:=r;
lazy:=inf;
end;
if l=r then exit;
mid:=(l+r)>>;
with tree[now] do
begin
lson:=tot+;
build(l,mid);
rson:=tot+;
build(mid+,r);
end;
end; procedure new(x,now:longint);
begin
with tree[now] do
begin
if left<>right then lazy:=x;
sum:=x*(right-left+);
amax:=max(,sum);
lmax:=amax;
rmax:=amax;
end;
end; procedure down(now:longint);
begin
with tree[now] do
begin
new(lazy,lson);
new(lazy,rson);
lazy:=inf;
end;
end; procedure up(now:longint);
begin
with tree[now] do
begin
sum:=tree[lson].sum+tree[rson].sum;
amax:=max(max(tree[lson].amax,tree[rson].amax),tree[lson].rmax+tree[rson].lmax);
lmax:=max(tree[lson].lmax,tree[lson].sum+tree[rson].lmax);
rmax:=max(tree[rson].rmax,tree[rson].sum+tree[lson].rmax);
end;
end; procedure change(x,now:longint);
var
mid:longint;
begin
with tree[now] do
begin
if(ll<=left)and(rr>=right) then
begin
new(x,now);
exit;
end;
if lazy<>inf then down(now);
mid:=(left+right)>>;
if rr>mid then change(x,rson);
if ll<=mid then change(x,lson);
up(now);
end;
end; procedure dfs2(x,t,ww:longint);
var
i:longint;
begin
flag[x]:=false;
top[x]:=t;
w[x]:=ww;
if son[x]= then
begin
root[x]:=tot+;
build(,ww);
ll:=ww;
rr:=ww;
change(a[x],root[x]);
exit;
end;
dfs2(son[x],t,ww+);
root[x]:=root[son[x]];
ll:=ww;
rr:=ww;
change(a[x],root[x]);
i:=first[x];
while i<> do
begin
if flag[last[i]] then dfs2(last[i],last[i],);
i:=next[i];
end;
end; procedure init;
var
i,x,y:longint;
begin
read(n);
for i:= to n do
read(a[i]);
for i:= to n- do
begin
read(x,y);
insert(x,y);
insert(y,x);
end;
dfs1(,,);
dfs2(,,);
end; procedure get(var am,lm,rm,su:longint;now:longint);
var
mid:longint;
begin
with tree[now] do
begin
if lazy<>inf then down(now);
if(ll<=left)and(rr>=right) then
begin
am:=max(max(am,amax),lm+rmax);
lm:=max(lmax,sum+lm);
rm:=max(rm,su+rmax);
su:=su+sum;
exit;
end;
mid:=(left+right)>>;
if rr>mid then get(am,lm,rm,su,rson);
if ll<=mid then get(am,lm,rm,su,lson);
end;
end; procedure work1;
var
x,y,amax1,lmax1,rmax1,sum1,amax2,lmax2,rmax2,sum2:longint;
begin
read(x,y);
amax1:=;
lmax1:=;
rmax1:=;
sum1:=;
amax2:=;
lmax2:=;
rmax2:=;
sum2:=;
if dep[top[x]]<dep[top[y]] then swap(x,y);
while top[x]<>top[y] do
begin
ll:=;
rr:=w[x];
get(amax1,lmax1,rmax1,sum1,root[x]);
x:=fa[top[x]];
if dep[top[x]]<dep[top[y]] then
begin
swap(x,y);
swap(amax1,amax2);
swap(lmax1,lmax2);
swap(rmax1,rmax2);
swap(sum1,sum2);
end;
end;
if dep[x]<dep[y] then
begin
swap(x,y);
swap(amax1,amax2);
swap(lmax1,lmax2);
swap(rmax1,rmax2);
swap(sum1,sum2);
end;
ll:=w[y];
rr:=w[x];
get(amax1,lmax1,rmax1,sum1,root[x]);
writeln(max(max(amax1,amax2),lmax1+lmax2));
end; procedure work2;
var
x,y,z:longint;
begin
read(x,y,z);
if dep[top[x]]<dep[top[y]] then swap(x,y);
while top[x]<>top[y] do
begin
ll:=;
rr:=w[x];
change(z,root[x]);
x:=fa[top[x]];
if dep[top[x]]<dep[top[y]] then swap(x,y);
end;
if dep[x]<dep[y] then swap(x,y);
ll:=w[y];
rr:=w[x];
change(z,root[x]);
end; procedure work;
var
i,q,s:longint;
begin
read(q);
for i:= to q do
begin
read(s);
if s= then work1
else work2;
end;
end; begin
init;
work;
end.

6779. Can you answer these queries VII - SPOJ的更多相关文章

  1. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  2. SPOJ GSS7 - Can you answer these queries VII

    板的不能再板,链剖+线段树或者是LCT随便维护. 感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳 ...

  3. SPOJ GSS7 Can you answer these queries VII ——树链剖分 线段树

    [题目分析] 问题放到了树上,直接链剖+线段树搞一搞. 调了300行+. (还是码力不够) [代码] #include <cstdio> #include <cstring> ...

  4. Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)

    You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defi ...

  5. Can you answer these queries(spoj 1043)

    题意:多次查询区间最长连续字段和 /* 用线段树维护区间最长子段和,最长左子段和,最长右子段和. */ #include<cstdio> #include<iostream> ...

  6. Can you answer these queries V SPOJ - GSS5 (分类讨论+线段树维护区间最大子段和)

    recursion有一个整数序列a[n].现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 &l ...

  7. SP6779 GSS7 - Can you answer these queries VII

    纯数据结构题,没有思维难度.直接用线段树求最大子段和的方法完成树上路径的合并.注意链上合并顺序要符合序列的前后顺序. #include <cstdio> #include <cstr ...

  8. 题解 SP6779 【GSS7 - Can you answer these queries VII】

    题目传送门 题目大意 给出一个\(n\)个点的树,每个点有权值.有\(m\)次操作,每次要么查询一条链上的最大子段和,要么把一条链的权值都修改为一个常数. \(n,m\le 10^5\) 思路 如果是 ...

  9. SP6779 GSS7 - Can you answer these queries VII(线段树,树链剖分)

    水题,只是坑点多,\(tag\)为\(0\)时可能也要\(pushdown\),所以要\(bool\)标记是否需要.最后树链剖分询问时注意线段有向!!! #include <cstring> ...

随机推荐

  1. CSS3 媒体记

    css3 媒体 Media Type 媒体类型 媒体类型是CSS2中一个非常有用的属性.通过媒体类型可以对不同的设备指定不同的样式. W3C共列出十种媒体类型,如表: 值 设备类型 all 所有设备 ...

  2. MyBatis(3.2.3) - Paginated ResultSets using RowBounds

    Sometimes, we may need to work with huge volumes of data, such as with tables with millions of recor ...

  3. css尖角

    .market-nav-arrow { ; ; ; border-style: solid; border-width: 7px 0px 7px 7px; border-color: transpar ...

  4. Android:Xml(读取与存储)

    1.读取XML文件 参数xml是建含xml数据的输入流,List<Person> persons用于存储xml流中的数据. XmlPullParser类的几个方法:next(),nextT ...

  5. Android第三方授权(QQ篇)

    QQ授权比微信授权相对来说会方便一些 同样需要去官网下载sdk和导入sdk到自己的工程 http://wiki.connect.qq.com/%E7%A7%BB%E5%8A%A8%E5%BA%94%E ...

  6. Ubuntu Linux 分区简易教程

    关于Linux系统下的“分区”问题,对于新手来说一直是很头疼的.我来简单写一下,它的“分区”方法,规则. 声明:我为了让没有接触过Linux系统的人,理解更加简单.所以在言语表述上不是很规范,专业.我 ...

  7. Java之绘制艺术图案

    前面已经介绍过绘制方法.这里不再赘述. package com.caiduping; import java.awt.Color; import java.awt.Graphics; import j ...

  8. CentOS6.3系统安装SCP命令

    原文:http://www.111cn.net/sys/CentOS/58387.htm CP使用SSH协议在Linux系统中进行文件传输,但我最小安装的CentOS 6.3没有该命令.  代码如下 ...

  9. Cocos移植到Android-通过命令行交叉编译打包

    当我们在Windows下使用Visual Studio开发好Win32平台的游戏程序后,我们需要把它们移植到不同的平台上.Cocos2d-x支持很多个平台,然而,我们不可能介绍全部平台的移植.我们总结 ...

  10. 值类型与引用类型(特殊的string) Typeof和GetType() 静态和非静态使用 参数传递 相关知识

    学习大神博客链接: http://www.cnblogs.com/zhili/category/421637.html 一 值类型与引用类型 需要注意的string 是特殊类型的引用类型. 使用方法: ...