dfs序,对结点进行重编号,要达到的目的是使子树节点的编号都大于父节点,编号完毕后,
如果某个节点是非叶子节点,那么它子树节点中的最大值和这个节点的编号代表的区间代表这个子树。
编号同时,根节点到此节点(包括此节点)的节点权值和求出,令存数组中。
这个新处理出的数组和要求的查询和修改就是(模板的区间求最大值及修改)。过程自行思考。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#define lt (2*root)
#define rt (2*root+1)
#define inf 0x3f3f3f3f3f3f3f3f;
using namespace std;
typedef __int64 LL;
LL a[101000];
LL b[101000];
LL head[101000],p,book[101000];
LL max(LL x,LL y){return x>y?x:y;}
struct NOde
{
LL Max,mark;
}v[401000];
struct Node
{
int l,r;LL s;//本采用全LL的数据类型,但莫名错误了,求解释?(换下行会WR..)
//LL l,r,s;
}c[101000];
struct Edge
{
LL u,v,next;
}edges[301000];
void build(LL root,LL l,LL r)
{
if(l==r){v[root].Max=b[l],v[root].mark=0;return;}
LL mid=(l+r)/2;
build(lt,l,mid);
build(rt,mid+1,r);
v[root].Max=max(v[lt].Max,v[rt].Max);
v[root].mark=0;
}
void done(LL root,LL value)
{
v[root].Max=v[root].Max+value;
v[lt].mark=v[lt].mark+value;
v[rt].mark=v[rt].mark+value;
}
void push_down(LL root)
{
if(v[root].mark)
{
v[root].Max=v[root].Max+v[root].mark;
v[lt].mark=v[lt].mark+v[root].mark;
v[rt].mark=v[rt].mark+v[root].mark;
v[root].mark=0;
}
}
void update(LL root,LL l,LL r,LL from,LL to,LL value)
{
push_down(root);
if(l>to||r<from) return;
if(l>=from&&r<=to){done(root,value);return;}
LL mid=(l+r)/2;
update(lt,l,mid,from,to,value);
update(rt,mid+1,r,from,to,value);
v[root].Max=max(v[lt].Max,v[rt].Max);
}
LL query(LL root,LL l,LL r,LL from,LL to)
{
push_down(root);
if(l>to||r<from) return -inf;
if(l>=from&&r<=to) return v[root].Max;
LL mid=(l+r)/2;
return max(query(lt,l,mid,from,to),query(rt,mid+1,r,from,to));
}
void addedges(LL u,LL v)
{
edges[p].u=u;
edges[p].v=v;
edges[p].next=head[u];
head[u]=p++;
}
LL id=1;
void dfs(LL st,LL sum)
{
c[st].s=sum+a[st];
book[st]=1;
c[st].l=id;
b[id]=sum+a[st];
for(LL i=head[st];i!=-1;i=edges[i].next)
{
LL to=edges[i].v;
if(book[to]) continue;
id=id+1;
dfs(to,sum+a[st]);
}
c[st].r=id;
book[st]=0;
}
void init(LL n)
{
id=1;
dfs(0,0);
build(1,1,n);
}
int main()
{
//freopen("C:/Users/hzy/Desktop/12.txt","r",stdin);
LL t,kcase=1;
scanf("%I64d",&t);
while(t--)
{
memset(head,-1,sizeof(head));
p=0;
LL n,m;
scanf("%I64d%I64d",&n,&m);
for(LL i=0;i<n-1;i++)
{
LL u,v;
scanf("%I64d%I64d",&u,&v);
addedges(u,v);
addedges(v,u);
}
for(LL i=0;i<n;i++) scanf("%I64d",&a[i]);
printf("Case #%I64d:\n",kcase++);
init(n);
while(m--)
{
LL op;
scanf("%I64d",&op);
if(op==1)
{
LL pos;
scanf("%I64d",&pos);
printf("%I64d\n",query(1,1,n,c[pos].l,c[pos].r));
}
else
{
LL pos,value;
scanf("%I64d%I64d",&pos,&value);
update(1,1,n,c[pos].l,c[pos].r,value-a[pos]);
a[pos]=value;
}
}
}
return 0;
}
线段树
最新推荐文章于 2024-04-18 08:24:29 发布