HYSBZ 4034 dfs序线段树
Posted chinesepikaync
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HYSBZ 4034 dfs序线段树相关的知识,希望对你有一定的参考价值。
题意反向翻译:
A tree with N points, with point 1 as the root, and the tree points have edge weights. Then there are M
There are three types of operations:
Operation 1: Increase a member‘s point weight by a.
Operation 2: Increase the point weights of all points in a subtree with x as the root by a.
Operation 3: Ask the sum of the weights of all points in the path from a shareholder x to the root.
The first line contains two integers N, M. Represents points and operands. The next line of N integers represents the initial weights of the nodes in the tree. Next N-1
Each row contains three positive integers fr, to, indicating that there is an edge (fr, to) in the tree. Then there are M lines, each of which represents an operation. among them
The first number indicates the kind of operation (1-3), followed by the parameter (x or xa) of this operation.
For each query operation, the answer to that query is output. Separate the answers with newlines.
欧拉序+线段树
A
/ B C
/ D E F
欧拉序就是进入到一个节点记一次,退出一个节点记一次
然后我们把进入到一个节点的那一次叫做+,退出的叫做-
ABDDEEBCFFCA
+++-+--++---
对 (u) 单点修改,因为对 (u) 加上一个 (val) 会对 (u) 的整个子树即 ([u_+,u_-)) 的答案产生影响,那么就在 (u_+) 加上 (val),在 (u_-) 减去 (val) 这样就不会影响到其他子树了
对 (u) 子树修改就相当于把整个 (u) 的子树进行单点修改,那么就把 ([u_+,u_-]) 中的所有 + 都加上 (val),所有 - 都减去 (val)
单点查询就直接查询 ([1,u_+]) 就行了
// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
#define int long long
using namespace std;
const int MaxN=100050;
struct Edge
{
int nxt,to;
}E[MaxN<<2];
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
int hd[MaxN],en,n,m;
int dfn[MaxN<<1],L[MaxN],R[MaxN],cnt;
int negative[MaxN<<1];
int cost[MaxN];
#define lson (u<<1)
#define rson (u<<1|1)
inline void adde(int u,int v)
{
++en;
E[en]=(Edge){hd[u],v};
hd[u]=en;
return;
}
inline void dfs(int u,int fa)
{
dfn[++cnt]=u;
L[u]=cnt;
negative[cnt]=0;
for(int i=hd[u];~i;i=E[i].nxt)
{
reg int v=E[i].to;
if(v==fa)
continue;
dfs(v,u);
}
dfn[++cnt]=u;
R[u]=cnt;
negative[cnt]=1;
return;
}
int val[MaxN<<4],nega[MaxN<<4],lazy[MaxN<<4];
inline void pushup(int u)
{
val[u]=val[lson]+val[rson];
nega[u]=nega[lson]+nega[rson];
return;
}
inline void pushdown(int u,int l,int r)
{
if(lazy[u])
{
reg int mid=(l+r)>>1;
lazy[lson]+=lazy[u];
lazy[rson]+=lazy[u];
val[lson]+=lazy[u]*(mid-l+1-2*nega[lson]);
val[rson]+=lazy[u]*(r-mid-2*nega[rson]);
lazy[u]=0;
}
return;
}
inline void buildtr(int u,int l,int r)
{
if(l==r)
{
if(negative[l])
{
val[u]=-cost[dfn[l]];
nega[u]=1;
}
else
{
val[u]=cost[dfn[l]];
nega[u]=0;
}
return;
}
reg int mid=(l+r)>>1;
buildtr(lson,l,mid);
buildtr(rson,mid+1,r);
pushup(u);
return;
}
inline void change(int u,int l,int r,int p,int k)
{
pushdown(u,l,r);
if(l==r)
{
val[u]+=k;
return;
}
reg int mid=(l+r)>>1;
if(p<=mid)
change(lson,l,mid,p,k);
else
change(rson,mid+1,r,p,k);
pushup(u);
return;
}
inline void modify(int u,int l,int r,int ql,int qr,int k)
{
pushdown(u,l,r);
if(ql<=l&&r<=qr)
{
val[u]+=k*(r-l+1-2*nega[u]);
lazy[u]+=k;
return;
}
reg int mid=(l+r)>>1;
if(ql<=mid)
modify(lson,l,mid,ql,qr,k);
if(mid<qr)
modify(rson,mid+1,r,ql,qr,k);
pushup(u);
return;
}
inline int query(int u,int l,int r,int ql,int qr)
{
pushdown(u,l,r);
if(ql<=l&&r<=qr)
return val[u];
reg int mid=(l+r)>>1,ans=0;
if(ql<=mid)
ans+=query(lson,l,mid,ql,qr);
if(mid<qr)
ans+=query(rson,mid+1,r,ql,qr);
return ans;
}
inline void print()
{
puts("=-=-=====-=-=-=-=");
puts("segment");
for(int i=1;i<=cnt;++i)
printf("%lld ",query(1,1,cnt,i,i));
puts("
=-=-==-=-=-=-=-=");
return;
}
signed main(void)
{
memset(hd,-1,sizeof hd);
cin>>n>>m;
reg int u,v;
for(int i=1;i<=n;++i)
read(cost[i]);
for(int i=1;i<n;++i)
{
read(u);read(v);
adde(u,v);
adde(v,u);
}
dfs(1,0);
buildtr(1,1,cnt);
// print();
reg int opt;
for(int i=1;i<=m;++i)
{
read(opt);read(u);
if(opt==1)
{
read(v);
change(1,1,cnt,L[u],v);
// printf("add %d 's val to %d
",L[u],v);
change(1,1,cnt,R[u],-v);
// printf("add %d 's val to %d
",R[u],-v);
}
else if(opt==2)
{
read(v);
modify(1,1,cnt,L[u],R[u],v);
// printf("modify [ %d , %d ] %d
",L[u],R[u],v);
}
else
printf("%lld
",query(1,1,cnt,1,L[u]));
// printf("Query [ %d , %d ]
",1,L[u]);
}
return 0;
}
以上是关于HYSBZ 4034 dfs序线段树的主要内容,如果未能解决你的问题,请参考以下文章