BZOJ 3653 谈笑风生

Posted on 2016-07-15 21:20  ziliuziliu  阅读(146)  评论(0编辑  收藏  举报

ORZ blutrex。。。。。。

主席树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 1000500
#define maxq 1000500
#define maxe 1600500
using namespace std;
struct edge
{
    long long v,nxt;
}e[maxe];
struct answer
{
    long long sum1,sum2;
};
long long n,q,x,y,nume=0,g[maxv],size[maxv],dis[maxv],w[maxv],mx[maxv],mxdis=0,cnt=0,fw[maxv];
long long root[maxv],ls[maxv<<3],rs[maxv<<3],val1[maxv<<3],val2[maxv<<3],tot=0;
void addedge(long long u,long long v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs(long long x,long long fath)
{
    size[x]=1;w[x]=++cnt;mx[x]=w[x];fw[cnt]=x;
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if (v!=fath)
        {
            dis[v]=dis[x]+1;mxdis=max(mxdis,dis[v]);
            dfs(v,x);
            size[x]+=size[v];
            mx[x]=max(mx[x],mx[v]);
        }
    }
}
void build(long long &now,long long left,long long right)
{
    now=++tot;val1[now]=val2[now]=0;
    if (left==right) return;
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void modify(long long last,long long &now,long long left,long long right,long long pos,long long x)
{
    now=++tot;ls[now]=ls[last];rs[now]=rs[last];
    val1[now]=val1[last]+x;val2[now]=val2[last]+1;
    if (left==right) return;
    long long mid=(left+right)>>1;
    if (pos<=mid) modify(ls[last],ls[now],left,mid,pos,x);
    else modify(rs[last],rs[now],mid+1,right,pos,x);
}
answer merge(answer x,answer y)
{
    answer ret;
    ret.sum1=x.sum1+y.sum1;
    ret.sum2=x.sum2+y.sum2;
    return ret;
}
answer ask(long long last,long long now,long long left,long long right,long long l,long long r)
{
    answer ret;
    if ((left==l) && (right==r))
    {
        ret.sum1=val1[now]-val1[last];
        ret.sum2=val2[now]-val2[last];
        return ret;
    }
    long long mid=(left+right)>>1;
    if (r<=mid) return ask(ls[last],ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[last],rs[now],mid+1,right,l,r);
    else return merge(ask(ls[last],ls[now],left,mid,l,mid),ask(rs[last],rs[now],mid+1,right,mid+1,r));
}
int main()
{
    scanf("%lld%lld",&n,&q);
    for (long long i=1;i<=n-1;i++)
    {
        scanf("%lld%lld",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    dfs(1,1);
    build(root[0],0,mxdis);
    for (long long i=1;i<=n;i++)
        modify(root[i-1],root[i],0,mxdis,dis[fw[i]],size[fw[i]]);
    for (long long i=1;i<=q;i++)
    {
        scanf("%lld%lld",&x,&y);
        long long ret=min(dis[x],y)*(size[x]-1);
        answer regis=ask(root[w[x]-1],root[mx[x]],0,mxdis,min(dis[x]+1,mxdis),min(dis[x]+y,mxdis));
        ret+=regis.sum1-regis.sum2;
        printf("%lld\n",ret);
    }
    return 0;
}