2836: 魔法树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 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=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; 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<<];
int cnt=,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<<];
#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=;
}
inline void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r; tree[now].size=r-l+;
if (l==r) return;
int mid=(l+r)>>;
BuildTree(ls,l,mid); BuildTree(rs,mid+,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)>>;
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)>>; LL re=;
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]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now])
{
deep[edge[i].to]=deep[now]+;
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(,pl[top[x]],pl[x],D);
x=fa[top[x]];
}
if (deep[x]>deep[y]) swap(x,y);
SegmentTree::Change(,pl[x],pl[y],D);
}
inline void Query(int x) {printf("%lld\n",SegmentTree::Query(,pl[x],pr[x]));}
}
int main()
{
N=read();
for (int x,y,i=; i<=N-; i++) x=read()+,y=read()+,InsertEdge(x,y);
TreePartition::DFS_1(); TreePartition::DFS_2(,);
SegmentTree::BuildTree(,,N);
Q=read();
while (Q--)
{
char opt[]; scanf("%s",opt); int u,v,D;
switch (opt[])
{
case 'A': u=read()+,v=read()+,D=read(); TreePartition::Change(u,v,D); break;
case 'Q': u=read()+; TreePartition::Query(u); break;
}
}
return ;
}
又无故RE了一次