【BZOJ4372】—烁烁的游戏(动态点分治)

传送门

动态点分治模板题

结果点分树建挂了。。。。

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>  
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=100005;
struct Bit{
    vector<int> tr;
    int n;
    inline void init(int _n){
        n=_n+1,tr.resize((n+1)<<2,0);
    }
    #define lb(x) (x&(-x))
    inline void update(int p,int k){p++;p=min(p,n);
        for(;p>=1;p-=lb(p))tr[p]+=k;
    }
    inline int query(int p,int res=0){p++;
        if(p<=0)return 0;
        for(;p<=n;p+=lb(p))res+=tr[p];return res;
    }
};
Bit f1[N],f2[N];
int n,m,maxn,rt;
int siz[N],son[N],vis[N];
vector<pii> fa[N];
vector<int> e[N];
void getrt(int u,int f){
    siz[u]=1,son[u]=0;
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==f||vis[v])continue;
        getrt(v,u),siz[u]+=siz[v];
        chemx(son[u],siz[v]);
    }
    son[u]=max(son[u],maxn-siz[u]);
    if(son[u]<son[rt])rt=u;
}
int mxdep;
void getdep(int u,int f,int dep){
    chemx(mxdep,dep);
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==f||vis[v])continue;
        getdep(v,u,dep+1);
    }
}
inline void init(Bit &x,int u,int dep){
    mxdep=0;
    getdep(u,0,dep);
    x.init(mxdep);
}
void givefa(int u,int f,int dep,int ff){
    fa[u].pb(pii(ff,dep));
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==f||vis[v])continue;
        givefa(v,u,dep+1,ff);
    }
}
void solve(int u,int f){
    vis[u]=1;
    init(f1[u],u,0),givefa(u,0,0,u);
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(vis[v])continue;
        maxn=siz[v]>siz[u]?siz[f]-siz[u]:siz[v];
        getrt(v,rt=0),init(f2[rt],v,1);
        solve(rt,u);
    }
}
inline int query(int u){
    int res=0;pii x;
    for(int i=fa[u].size()-1;~i;i--){
        x=fa[u][i];
        res+=f1[x.fi].query(x.se);
    }
    for(int i=fa[u].size()-1;i;i--){
        res-=f2[fa[u][i].fi].query(fa[u][i-1].se);
    }
    return res;
}
inline void update(int u,int d,int k){
    pii x;
    for(int i=(int)fa[u].size()-1;~i;i--){
        x=fa[u][i];
        f1[x.fi].update(d-x.se,k);
    }
    for(int i=(int)fa[u].size()-1;i;i--){
        f2[fa[u][i].fi].update(d-fa[u][i-1].se,k);
    }
}
char op[4];
int main(){
    n=read(),m=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        e[u].pb(v),e[v].pb(u);
    }
    siz[0]=son[0]=maxn=n;
    getrt(1,rt=0);
    solve(rt,0);
    while(m--){
        scanf("%s",op+1);int x=read();
        if(op[1]=='Q'){
            cout<<query(x)<<'\n';
        }
        else{
            int d=read(),w=read();
            update(x,d,w);
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值