• [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
    ",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
  • 相关阅读:
    软件构造 第七章第三节 断言和防御性编程
    软件构造 第七章第二节 错误与异常处理
    软件构造 第七章第一节 健壮性和正确性的区别
    软件构造 第六章第三节 面向可维护的构造技术
    软件构造 第六章第二节 可维护的设计模式
    欧拉函数代码实现及扩展--快速矩阵幂
    编译原理
    算法设计与分析总结
    人工智能简答总结
    感想
  • 原文地址:https://www.cnblogs.com/wang9897/p/10347361.html
Copyright © 2020-2023  润新知