[BZOJ]2836: 魔法树

题解:树链剖分裸题

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}

int num[MAXN],dep[MAXN],fa[MAXN],son[MAXN],n,q;
void dfs1(int x,int pre,int deep){
    fa[x]=pre;dep[x]=deep+1;num[x]=1;
    link(x){
	if(j->t==pre)continue;
	dfs1(j->t,x,deep+1);
	num[x]+=num[j->t];
	if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
    }
}

ll flag[MAXN<<2],sum[MAXN<<2];

void push(int rt,int l,int r){
    if(flag[rt]){
	int mid=(l+r)>>1;
	flag[rt<<1]+=flag[rt];flag[rt<<1|1]+=flag[rt];
	sum[rt<<1]+=1ll*(mid-l+1)*flag[rt];
	sum[rt<<1|1]+=1ll*(r-mid)*flag[rt];
	flag[rt]=0;
    }
}

void update(int rt,int l,int r,int ql,int qr,int t){
    if(ql<=l&&r<=qr){
	sum[rt]+=1ll*(r-l+1)*t;flag[rt]+=t;
	return ;
    }
    int mid=(l+r)>>1;
    push(rt,l,r);
    if(ql<=mid)update(rt<<1,l,mid,ql,qr,t);
    if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,t);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
ll ans;
void query(int rt,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){ans+=sum[rt];return ;}
    int mid=(l+r)>>1;
    push(rt,l,r);
    if(ql<=mid)query(rt<<1,l,mid,ql,qr);
    if(qr>mid)query(rt<<1|1,mid+1,r,ql,qr);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

int tp[MAXN],p[MAXN],cnt;
void dfs2(int x,int td){
    tp[x]=td;p[x]=++cnt;
    if(son[x]!=-1)dfs2(son[x],td);
    link(x){
	if(j->t==fa[x]||son[x]==j->t)continue;
	dfs2(j->t,j->t);
    }
}

void Add(int u,int v,int t){
    int uu=tp[u];int vv=tp[v];
    while(uu!=vv){
	if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
	update(1,1,n,p[uu],p[u],t);
	u=fa[uu];uu=tp[u];
    }
    if(dep[u]>dep[v])swap(u,v);
    update(1,1,n,p[u],p[v],t);
}

ll Query(int u){
    ans=0;query(1,1,n,p[u],p[u]+num[u]-1);
    return ans;
}

int main(){
    n=read();
    int u,v,t;
    inc(i,1,n)son[i]=-1;
    inc(i,2,n)u=read()+1,v=read()+1,add(u,v),add(v,u);
    dfs1(1,0,0);dfs2(1,1);
    q=read();
    char str[11];
    while(q--){
	scanf("%s",str);u=read()+1;
	if(str[0]=='Q')printf("%lld\n",Query(u));
	else v=read()+1,t=read(),Add(u,v,t);
    }
    return 0;
}

  

2836: 魔法树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 625  Solved: 245
[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

Sample Output

3
3
2
posted @ 2019-02-02 00:10  wang9897  阅读(217)  评论(0编辑  收藏  举报