题意反向翻译:
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("\n=-=-==-=-=-=-=-="); 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\n",L[u],v); change(1,1,cnt,R[u],-v); // printf("add %d 's val to %d\n",R[u],-v); } else if(opt==2) { read(v); modify(1,1,cnt,L[u],R[u],v); // printf("modify [ %d , %d ] %d\n",L[u],R[u],v); } else printf("%lld\n",query(1,1,cnt,1,L[u])); // printf("Query [ %d , %d ] \n",1,L[u]); } return 0; }
来源:https://www.cnblogs.com/chinesepikaync/p/12485547.html