题目链接http://xcacm.hfut.edu.cn/problem.php?id=1103

题目大意:链更新。链查询,求树链的最大子段和。(子段可以为空)

解题思路

将所有Query离线存储,并且注明哪个是更新,哪个是查询。

Tarjan离线处理中,记录每个结点的前驱,p[v]=u。

若更新,从u点回溯到LCA,从v点回溯到LCA,逐个修改。

若查询,将u点回溯到LCA,LCA,v点回溯到LCA的倒序拼成一个序列,求最大子段和。

值得注意的是,子段和全为负值的时候,ans=max(0,ans),即不要任何插线板(原题意思不明)。

#include "cstdio"
#include "cstring"
#include "vector"
#include "algorithm"
using namespace std;
#define maxn 100005
#define inf 0x3f3f3f3f
int head[maxn],qhead[maxn],lag[maxn],kth[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn],p[maxn],s1[maxn],s2[maxn];
bool isUpdate[maxn];
struct Edge
{
int to,next;
}e[maxn*];
struct Query
{
int from,to,next,idx,c;
}q[maxn*];
void addedge(int u,int v)
{
e[tot1].to=v;
e[tot1].next=head[u];
head[u]=tot1++;
}
void addquery(int u,int v,int idx,int c=inf)
{
q[tot2].from=u;
q[tot2].to=v;
q[tot2].next=qhead[u];
q[tot2].idx=idx;
if(c!=inf) q[tot2].c=c;
qhead[u]=tot2++;
}
int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
void Union(int u,int v)
{
u=find(u),v=find(v);
if(u!=v) f[v]=u;
}
void LCA(int u)
{
vis[u]=true;
f[u]=u;
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
p[v]=u;
LCA(v);
Union(u,v);
}
}
for(int i=qhead[u];i!=-;i=q[i].next)
{
int v=q[i].to;
if(vis[v]) ancestor[q[i].idx]=find(v);
//or storage e[i].lca=e[i^1].lca=find(v)
}
}
int sum(int num)
{
s2[]=s1[];
int Max=s2[];
for(int i=; i<num; i++)
{
if(s2[i-]>) s2[i]=s2[i-]+s1[i];
else s2[i]=s1[i];
if(s2[i]>Max) Max=s2[i];
}
return max(,Max);
}
int main()
{
//freopen("in.txt","r",stdin);
int T,n,m,u,v,c,cmd,qcnt=;
scanf("%d",&n);
tot1=tot2=;
memset(head,-,sizeof(head));
memset(qhead,-,sizeof(qhead));
memset(vis,,sizeof(vis));
memset(isUpdate,,sizeof(isUpdate));
for(int i=;i<=n;i++) scanf("%d",&lag[i]);
for(int i=; i<n-; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
scanf("%d",&m);
for(int i=; i<m; i++)
{
scanf("%d",&cmd);
if(cmd==)
{
scanf("%d%d%d",&u,&v,&c);
addquery(u,v,i,c);
addquery(v,u,i,c);
isUpdate[i]=true;
}
else
{
scanf("%d%d",&u,&v);
addquery(u,v,i);
addquery(v,u,i);
}
}
LCA();
vector<int> ans;
for(int i=; i<tot2; i=i+)
{
int u=q[i].from,v=q[i].to,idx=q[i].idx;
int ed=ancestor[idx],cnt=;
if(isUpdate[qcnt])
{
int c=q[i].c;
while(u!=ed) lag[u]=c,u=p[u];
lag[ed]=c;
while(v!=ed) lag[v]=c,v=p[v];
}
else
{
while(u!=ed) s1[cnt++]=lag[u],u=p[u];
s1[cnt++]=lag[ed];
vector<int> rev;
while(v!=ed) rev.push_back(lag[v]),v=p[v];
for(int j=rev.size()-; j>=; j--) s1[cnt++]=rev[j];
int x=sum(cnt);
ans.push_back(x);
}
qcnt++;
}
for(int i=;i<ans.size()-;i++) printf("%d ",ans[i]);
printf("%d\n",ans[ans.size()-]);
}

XCOJ 1103 (LCA+树链最大子段和)的更多相关文章

  1. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  2. [BZOJ3626] [LNOI2014]LCA(树链剖分)

    [BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...

  3. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  4. Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分

    D. Happy Tree Party     Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...

  5. HDU 3078 (LCA+树链第K大)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题目大意:定点修改.查询树中任意一条树链上,第K大值. 解题思路: 先用离线Tarjan把每个 ...

  6. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  7. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)

    Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花 ...

  8. BZOJ3626[LNOI2014]LCA——树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  9. bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...

随机推荐

  1. Volley学习总结

    本文主要包括以下内容 volly基本操作(String与Json类型) volly图片操作 自定义volly volly源码分析 Volley简单易用,在性能方面也进行了大幅度的调整,它的设计目标就是 ...

  2. myaql常用函数

    一.数学函数 abs(x)   返回x的绝对值 bin(x)   返回x的二进制(oct返回八进制,hex返回十六进制) ceiling(x)   返回大于x的最小整数值 exp(x)   返回值e( ...

  3. mysql里表以及列的增删改查

    在一个表里插入数据(增)   insert into 表名 (需要插入的列名如  id,name,age)values    (1,'张三',20), (2,'李四',30):     查询表内容(查 ...

  4. JS添加MD5,JS提示框

    http://pan.baidu.com/s/1kTmSp9t

  5. DOM – 4.doucument属性

    4.document属性 2.1 write 2.2 getElementById 方法 getElementsByName getElementsByTagName 案例:全选反选 案例:点击一个按 ...

  6. C#的扩展方法

    using System; using System.Collections; using System.Collections.Generic; using System.IO; using Sys ...

  7. 菜鸟学Linux命令:lsof命令 查找指定用户、进程、端口打开的文件

    lsof,list open files, 是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件. 命令格式:ls ...

  8. Delphi函数指针

    参考:http://blog.chinaunix.net/uid-91034-id-2009700.html http://blog.csdn.net/procedure1984/article/de ...

  9. STL Map的使用

    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力.下面就通过示例记录一下map的使用: 一.向map中 ...

  10. [SQL]查询及删除重复记录的SQL语句

    一:查询及删除重复记录的SQL语句1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select ...