2836: 魔法树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 323 Solved: 129
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4
0 1
1 2
2 3
4
Add 1 3 1
Query 0
Query 1
Query 2
0 1
1 2
2 3
4
Add 1 3 1
Query 0
Query 1
Query 2
Sample Output
3
3
2
3
2
HINT
Source
Solution
树链修改,子树查询,可以直接树链剖分搞定
注意sum和tag要开longlong
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define INF 0x7fffffff #define MAXN 100010 #define MAXM 100010 #define LL long long int N,Q; struct EdgeNode{int next,to;}edge[MAXN<<1]; int cnt=1,head[MAXN]; inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} namespace SegmentTree { struct SegmentTreeNode{int l,r,size; LL sum,tag;}tree[MAXN<<2]; #define ls now<<1 #define rs now<<1|1 inline void Update(int now) {tree[now].sum=tree[ls].sum+tree[rs].sum;} inline void PushDown(int now) { if (!tree[now].tag || tree[now].l==tree[now].r) return; tree[ls].sum+=(LL)tree[ls].size*tree[now].tag; tree[ls].tag+=tree[now].tag; tree[rs].sum+=(LL)tree[rs].size*tree[now].tag; tree[rs].tag+=tree[now].tag; tree[now].tag=0; } inline void BuildTree(int now,int l,int r) { tree[now].l=l; tree[now].r=r; tree[now].size=r-l+1; if (l==r) return; int mid=(l+r)>>1; BuildTree(ls,l,mid); BuildTree(rs,mid+1,r); Update(now); } inline void Change(int now,int L,int R,int D) { int l=tree[now].l,r=tree[now].r; if (L<=l && R>=r) {tree[now].tag+=D; tree[now].sum+=(LL)tree[now].size*D; return;} PushDown(now); int mid=(l+r)>>1; if (L<=mid) Change(ls,L,R,D); if (R>mid) Change(rs,L,R,D); Update(now); } inline LL Query(int now,int L,int R) { int l=tree[now].l,r=tree[now].r; if (L<=l && R>=r) return tree[now].sum; PushDown(now); int mid=(l+r)>>1; LL re=0; if (L<=mid) re+=Query(ls,L,R); if (R>mid) re+=Query(rs,L,R); return re; } } namespace TreePartition { int fa[MAXN],size[MAXN],son[MAXN],deep[MAXN],pl[MAXN],dfn,pr[MAXN],pre[MAXN],top[MAXN]; inline void DFS_1(int now) { size[now]=1; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=fa[now]) { deep[edge[i].to]=deep[now]+1; fa[edge[i].to]=now; DFS_1(edge[i].to); size[now]+=size[edge[i].to]; if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to; } } inline void DFS_2(int now,int chain) { top[now]=chain; pl[now]=++dfn; pre[dfn]=now; if (son[now]) DFS_2(son[now],chain); for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=fa[now] && edge[i].to!=son[now]) DFS_2(edge[i].to,edge[i].to); pr[now]=dfn; } inline void Change(int x,int y,int D) { while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); SegmentTree::Change(1,pl[top[x]],pl[x],D); x=fa[top[x]]; } if (deep[x]>deep[y]) swap(x,y); SegmentTree::Change(1,pl[x],pl[y],D); } inline void Query(int x) {printf("%lld ",SegmentTree::Query(1,pl[x],pr[x]));} } int main() { N=read(); for (int x,y,i=1; i<=N-1; i++) x=read()+1,y=read()+1,InsertEdge(x,y); TreePartition::DFS_1(1); TreePartition::DFS_2(1,1); SegmentTree::BuildTree(1,1,N); Q=read(); while (Q--) { char opt[10]; scanf("%s",opt); int u,v,D; switch (opt[0]) { case 'A': u=read()+1,v=read()+1,D=read(); TreePartition::Change(u,v,D); break; case 'Q': u=read()+1; TreePartition::Query(u); break; } } return 0; }
又无故RE了一次