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. CentOS安装Node.js简单教程

    记录一下自己安装过程 先安装gcc-c++编译环境和openssl  代码如下 复制代码 yum install gcc-c++ openssl-devel wget http://nodejs.or ...

  2. CSU-ACM2016暑假集训训练1-二分搜索 A - Can you find it?

    Time Limit:3000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Description Give yo ...

  3. Item47

    STL迭代器分类:input迭代器.output迭代器.forward迭代器.bidirectional迭代器.random access迭代器. Input迭代器:只能向前移动,一次一步,客户只读取 ...

  4. 抓包分析TCP的三次握手和四次分手

    一:三次握手 三次的握手的过程是: 1.由发起方HostA向被叫方HostB发出请求报文段,此时首部中的同步位SYN=1,同时选择一个序列号seq=x.TCP规定,SYN报文(即SYN=1的报文段)不 ...

  5. [转载]mysql慢日志文件分析处理

    原文地址:mysql慢日志文件分析处理作者:maxyicha mysql有一个功能就是可以log下来运行的比较慢的sql语句,默认是没有这个log的,为了开启这个功能,要修改my.cnf或者在mysq ...

  6. 串操作,C++实现

    对串的基本操作都全已经实现 对kmp,kf字符串替换等功能全都已经实现 由于时间原因.没来得及注释,希望大家参考见谅. 串操作hstring.h头文件实现 //kallen 1 #ifndef _HS ...

  7. 一个汉字的ASCII编码&#12288;

    一个汉字的ASCII编码:  

  8. LAMP(Ubuntu+apache+mysql+php)+Zend Studio 新手の PHP的开发环境搭建

    因为工作需要,就从c#转型过来研究PHP.可是没想到从一开始就遇上了问题,环境配置方面的问题足足令我头疼了两天.因为博主本人对于linux的接触非常少,所以在解决这个问题的时候也学到了不少东西, 非常 ...

  9. RadComboBox的用法

    AutoPostBack="true",自动回传数据,也就是自动刷新 <telerik:RadComboBox ID="rcbTeacherList" r ...

  10. 【CSDN人物访谈】蒋守壮分享他的技术成长之路以及对Hive技术的解读与思考

    结缘大数据技术 CSDN:请简单地介绍一下自己. 蒋守壮:首先非常感谢CSDN能够给我这次被专访的机会,可以让我重新审视自己的职业发展历程,也希望能够帮助一些同行的朋友们.目前就职万达网络科技集团有限 ...