【[湖南集訓]談笑風生】
阿新 • • 發佈:2019-01-02
裏的 return ring dfs cpp 查詢 深度 節點 printf 也只能在\(a\)的子樹裏選取,所以權值是\(sum[a]-1\),至於\(b\)的選擇我們就可以從\(a\)往上的\(k\)個節點
主席樹板子了
首先看到這個暴力異常的題面,感覺做了這道題的會沒命的
首先先考慮\(b\)在\(a\)子樹內部的情況,這個樣子的話我們需要知道子樹內部所有深度小於等於\(deep[a]+k\)的點帶來的貢獻是是多少,由於這裏的\(a,b,c\)都不能是同一個節點,所以這裏的貢獻就是子樹大小減1,同時\(b\)也不能是\(a\)
之後按照深度建主席樹就好了,權值是子樹大小減1,我們就可以快速的查詢點子樹內部所有距離它的點小於等於\(k\)的點帶來的權值和了
之後在考慮子樹外部的情況,由於\(a,b\)都是\(c\)的祖先,所以\(b\)不在\(a\)子樹內部的話就必定在\(a\)到根的路徑上,而\(c\)
代碼
#include<iostream> #include<cstring> #include<cstdio> #define re register #define maxn 300005 #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define LL long long struct E { int v,nxt; }e[maxn<<1]; int l[maxn*20],r[maxn*20]; LL d[maxn*20]; int cnt,tot; int build(int x,int y) { int root=++cnt; if(x==y) return root; int mid=x+y>>1; l[root]=build(x,mid); r[root]=build(mid+1,y); return root; } int change(int pre,int x,int y,int pos,LL val) { int root=++cnt; d[root]=d[pre]+val; if(x==y) return root; l[root]=l[pre],r[root]=r[pre]; int mid=x+y>>1; if(pos<=mid) l[root]=change(l[pre],x,mid,pos,val); else r[root]=change(r[pre],mid+1,y,pos,val); return root; } LL query(int pos,int x,int y,int xx,int yy) { if(xx<=x&&yy>=y) return d[pos]; int mid=x+y>>1; if(yy<=mid) return query(l[pos],x,mid,xx,yy); if(xx>mid) return query(r[pos],mid+1,y,xx,yy); return query(l[pos],x,mid,xx,yy)+query(r[pos],mid+1,y,xx,yy); } int head[maxn],deep[maxn],to[maxn],rt[maxn],_to[maxn]; LL p[maxn],sum[maxn]; int n,Q,num,maxdep; inline void add_edge(int x,int y) { e[++num].v=y; e[num].nxt=head[x]; head[x]=num; } inline int read() { char c=getchar(); int x=0; while(c<‘0‘||c>‘9‘) c=getchar(); while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } void dfs(int x) { sum[x]=1; to[x]=++tot; _to[tot]=x; for(re int i=head[x];i;i=e[i].nxt) if(!deep[e[i].v]) { deep[e[i].v]=deep[x]+1; p[e[i].v]=p[x]+1; dfs(e[i].v); sum[x]+=sum[e[i].v]; } maxdep=max(maxdep,deep[x]); } int main() { n=read();Q=read(); int x,y; for(re int i=1;i<n;i++) { x=read(),y=read(); add_edge(x,y),add_edge(y,x); } deep[1]=1; dfs(1); rt[0]=build(1,maxdep); for(re int i=1;i<=n;i++) rt[i]=change(rt[i-1],1,maxdep,deep[_to[i]],sum[_to[i]]-1); LL k; while(Q--) { x=read(),k=read(); LL ans=0; ans=min(p[x],k)*(sum[x]-1); y=to[x]+sum[x]-1; if(deep[x]!=maxdep) ans+=query(rt[y],1,maxdep,deep[x]+1,min(deep[x]+k,maxdep))-query(rt[to[x]-1],1,maxdep,deep[x]+1,min(deep[x]+k,maxdep)); printf("%lld",ans),putchar(10); } return 0; }
【[湖南集訓]談笑風生】