BZOJ3653: 谈笑风生

先跑出dfs序。。然后对于询问p,k ans=min(k,dep[p])*s[p]+∑s[y]

y是p子树上的点且满足距离限制。

只要对dfs序建可持久化线段树就可以快速求出∑s[y]

(权当复习可持久化线段树了。。。询问的时候因为这是一棵可持久化线段树,所以访问到的节点如果是空就要退出来不然就要T。。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 300500
#define inf 0x7fffffff
#define ll long long
#define mm 100000007
using namespace std;
struct data{int obj,pre;
}e[maxn*2];
int head[maxn],l[maxn],r[maxn];
int s[maxn],num[maxn],dep[maxn];
int root[maxn],lc[maxn*20],rc[maxn*20];
ll sum[maxn*20];
int tot,cnt,n,mx,idx,m;
int 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;
}
void insert(int x,int y){
    e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot; 
}
void dfs(int u,int f){
    l[u]=++idx; num[idx]=u;
    for (int j=head[u];j;j=e[j].pre){
        int v=e[j].obj;
        if (v==f) continue;
        dep[v]=dep[u]+1; mx=max(mx,dep[v]);
        dfs(v,u);
        s[u]+=s[v]+1;
    }
    r[u]=idx;
}
void add(int l,int r,int x,int &y,int val,int pos){
    y=++cnt;
    sum[y]=sum[x]+1LL*val;
    if (l==r) return;
    lc[y]=lc[x]; rc[y]=rc[x];
    int mid=(l+r)/2;
    if (pos<=mid) add(l,mid,lc[x],lc[y],val,pos);
    else add(mid+1,r,rc[x],rc[y],val,pos);
}
ll ask(int l,int r,int x,int L,int R){
    if (!x) return 0;
    if (L<=l&&r<=R) return sum[x];
    int mid=(l+r)/2;
    if (R<=mid) return ask(l,mid,lc[x],L,R);
    else if (L>mid) return ask(mid+1,r,rc[x],L,R);
    else return ask(l,mid,lc[x],L,mid)+ask(mid+1,r,rc[x],mid+1,R);
}
int main(){
    n=read(); m=read();
    rep(i,1,n-1){
        int x=read(),y=read();
        insert(x,y); insert(y,x);
    }
    dfs(1,0);
    rep(i,1,n) add(0,mx,root[i-1],root[i],s[num[i]],dep[num[i]]);
    rep(i,1,m){
        int x=read(),y=read();
        ll ans=1LL*min(y,dep[x])*s[x];
        int L=dep[x]+1,R=min(mx,dep[x]+y);
        ans+=ask(0,mx,root[r[x]],L,R);
        ans-=ask(0,mx,root[l[x]-1],L,R);
        printf("%lld\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(BZOJ3653: 谈笑风生)