您的位置:首页 > 其它

【BZOJ 3653】 谈笑风生|主席树

2016-04-21 06:35 375 查看
好神的思路

按dfs序建树 深度作为范围

详见黄学长等

wa了一次

1.没有 long long 输出

2.询问的时候没有加root[]调试很长时间

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int MAXN=300000+10;
int cnt,s[MAXN],t[MAXN],size[MAXN],depth[MAXN],fa[MAXN],fx[MAXN];
int top,root[MAXN],max_depth,to[MAXN*20][2];
LL Num[MAXN*20];
int tot,g[MAXN],nnext[MAXN*2],num[MAXN*2];
void add(int x,int y)
{
tot++;
nnext[tot]=g[x];
g[x]=tot;
num[tot]=y;
}
void dfs(int x)
{
depth[x]=depth[fa[x]]+1;
max_depth=max(max_depth,depth[x]);
s[x]=++cnt;
fx[cnt]=x;
size[x]=1;
for(int i=g[x];i;i=nnext[i])
if(num[i]!=fa[x])
{
fa[num[i]]=x;
dfs(num[i]);
size[x]+=size[num[i]];
}
t[x]=cnt;
}
int n,q;
void add(int last,int now,int l,int r,int x,int y)
{
Num[now]=Num[last]+y;
if(l==r) return ;
int mid=(l+r)/2;
if(x<=mid) to[now][1]=to[last][1],to[now][0]=++top,add(to[last][0],to[now][0],l,mid,x,y);
else to[now][0]=to[last][0],to[now][1]=++top,add(to[last][1],to[now][1],mid+1,r,x,y);
}
LL qq(int last,int now,int l,int r,int ss,int tt)
{
// cout<<l<<" "<<r<<endl;
if(ss<=l&&r<=tt) return Num[now]-Num[last];
int mid=(l+r)/2;
LL ans=0;
if(ss<=mid) ans+=qq(to[last][0],to[now][0],l,mid,ss,tt);
if(mid+1<=tt) ans+=qq(to[last][1],to[now][1],mid+1,r,ss,tt);
return ans;
}
int main()
{
cin>>n>>q;
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1);
for(int i=1;i<=n;i++) root[i]=++top,add(root[i-1],root[i],1,max_depth,depth[fx[i]],size[fx[i]]-1);
// for(int i=1;i<=n;i++) cout<<Num[root[i]]<<' ';
//cout<<endl;
//cout<<'*'<<qq(root[3],root[5],1,max_depth,1,4);

for(int i=1;i<=q;i++)
{
LL ans=0;
int x,y;
scanf("%d %d",&x,&y);
ans+=((LL)min(y,depth[x]-1)*(size[x]-1));//cout<<s[x]<<' '<<t[x]<<endl;
ans+=qq(root[s[x]],root[t[x]],1,max_depth,depth[x]+1,depth[x]+y);
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: