2018沈阳网络赛J

给一颗树,两种操作,一种把同一层的点权值加上v,另一种求一点下的子树权值和。

按层数中点个数分块,小块直接暴力把所有点用bit更新,大块把层的值存下来。

询问的时候子树权值和为bit中的值以及其下面的点在大块中的值,下面中的点在大块中的值用二分实现。

#include <bits/stdc++.h>
#include <unordered_set>
#include <unordered_map>
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define rep(i,x,y) for(i=x;i<=y;i++)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define up rt,rt<<1,rt<<1|1
#define mem(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define LMissher
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e5+7;
const double pi = acos(-1);
const int inf = 2147483647;
const int mod = 1e9+7;

int n,q,i;
int cnt,head[M],tot,dep;
vector<int> d[M];
vector<int> lg;
int in[M],out[M];
ll ans[M],c[M];
void init(){
    tot=cnt=0;
    mem1(head);
}
struct edge
{
    int v,nex;
}e[M<<1];
void add(int u,int v){
    e[++cnt].v=v;e[cnt].nex=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa,int de){
    dep=max(de,dep);
    in[u]=++tot;
    d[de].pb(in[u]);
    for(int j=head[u];~j;j=e[j].nex){
        int v=e[j].v;
        if(v==fa) continue;
        dfs(v,u,de+1);
    }
    out[u]=tot;
}
void update(int x,ll v){
    for(;x<=n;x+=x&(-x)){
        c[x]+=v;
    }
}
ll query(int x){
    ll tmp=0;
    for(;x;x-=x&(-x)) tmp+=c[x];
    return tmp;
}
int main(){
    #ifdef LMissher
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    init();
    scanf("%d%d",&n,&q);
    rep(i,1,n-1){
        int from,to;
        scanf("%d%d",&from,&to);
        add(from,to);add(to,from);
    }
    dep=0;
    dfs(1,-1,0);
    int block=1<<12;
    rep(i,0,dep){
        if(d[i].size()>block) lg.pb(i);
    }
    int op,l,v,rt;
    while(q--){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&l,&v);
            if(d[l].size()>block) ans[l]+=1ll*v;
            else{
                for(i=0;i<d[l].size();i++){
                    update(d[l][i],v*1ll);
                }
            }
        }
        else{
            scanf("%d",&rt);
            ll aa=query(out[rt])-query(in[rt]-1);
            for(i=0;i<lg.size();i++){
                aa+=(upper_bound(d[lg[i]].begin(),d[lg[i]].end(),out[rt])-lower_bound(d[lg[i]].begin(),d[lg[i]].end(),in[rt]))*ans[lg[i]];
            }
            printf("%lld\n",aa);
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9611076.html