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

来源:互联网 发布:软件测试工程师要求 编辑:程序博客网 时间:2024/06/04 18:02

好神的思路

按dfs序建树 深度作为范围

详见黄学长等


wa了一次

1.没有 long long 输出

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


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define LL long longconst 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;}


0 0
原创粉丝点击