P3899 [湖南集训]谈笑风生

Posted yiqiatiya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3899 [湖南集训]谈笑风生相关的知识,希望对你有一定的参考价值。

P3899 [湖南集训]谈笑风生

二维数点问题,主席树模板(两种写法

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define pb push_back
using namespace std;
const int N=3e5+3;
struct hh{
  int to,nxt;
}e[N<<1];
int n,m,num,fir[N],dfn[N],dep[N],siz[N],Max;
vector<int>p[N];
int cnt,rt[N],ls[N*400],rs[N*400];
LL sum[N*400],ans;
IL int in(){
  char c;int f=1;
  while((c=getchar())<‘0‘||c>‘9‘)
    if(c==‘-‘) f=-1;
  int x=c-‘0‘;
  while((c=getchar())>=‘0‘&&c<=‘9‘)
    x=x*10+c-‘0‘;
  return x*f;
}
IL void add(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
void upd(int &o,int p,int l,int r,int u,int v){
  o=++cnt,ls[o]=ls[p],rs[o]=rs[p],sum[o]=sum[p]+v;
  if(l==r) return;
  int mid=l+r>>1;
  if(u<=mid) upd(ls[o],ls[p],l,mid,u,v);
  else upd(rs[o],rs[p],mid+1,r,u,v);
}
LL query(int o,int l,int r,int ll,int rr){
  if(!o) return 0;
  if(l>=ll&&r<=rr) return sum[o];
  int mid=l+r>>1;
  if(rr<=mid) return query(ls[o],l,mid,ll,rr);
  if(ll>mid) return query(rs[o],mid+1,r,ll,rr);
  return query(ls[o],l,mid,ll,rr)+query(rs[o],mid+1,r,ll,rr);
}
void dfs(int u,int fa){
  dep[u]=dep[fa]+1,siz[u]=1,dfn[u]=++num,p[dep[u]].pb(u),Max=max(Max,dep[u]);
  for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    if(v^fa) dfs(v,u),siz[u]+=siz[v];
}
int main()
{
	int x,y;
	n=in(),m=in();
	for(int i=1;i<n;++i)
	  x=in(),y=in(),
	  add(x,y),add(y,x);
	num=0,dfs(1,0);
	for(int i=1;i<=Max;++i)
	  for(int j=0;j<p[i].size();++j)
	    if(!j) upd(rt[i],rt[i-1],1,n,dfn[p[i][j]],siz[p[i][j]]-1);
	    else upd(rt[i],rt[i],1,n,dfn[p[i][j]],siz[p[i][j]]-1);
	while(m--){
	  x=in(),y=in();
	  ans=1ll*min(dep[x]-1,y)*(siz[x]-1);
	  if(siz[x]^1) ans+=query(rt[min(Max,dep[x]+y)],1,n,dfn[x]+1,dfn[x]+siz[x]-1);
	  printf("%lld
",ans);
	}
  return 0;
}
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define pb push_back
using namespace std;
const int N=3e5+3;
struct hh{
  int to,nxt;
}e[N<<1];
int n,m,num,fir[N],dfn[N],dep[N],siz[N],rev[N],Max;
int cnt,rt[N],ls[N*400],rs[N*400];
LL sum[N*400],ans;
IL int in(){
  char c;int f=1;
  while((c=getchar())<‘0‘||c>‘9‘)
    if(c==‘-‘) f=-1;
  int x=c-‘0‘;
  while((c=getchar())>=‘0‘&&c<=‘9‘)
    x=x*10+c-‘0‘;
  return x*f;
}
IL void add(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
void upd(int &o,int p,int l,int r,int u,int v){
  o=++cnt,ls[o]=ls[p],rs[o]=rs[p],sum[o]=sum[p]+v;
  if(l==r) return;
  int mid=l+r>>1;
  if(u<=mid) upd(ls[o],ls[p],l,mid,u,v);
  else upd(rs[o],rs[p],mid+1,r,u,v);
}
LL query(int o,int l,int r,int ll,int rr){
  if(!o) return 0;
  if(l>=ll&&r<=rr) return sum[o];
  int mid=l+r>>1;
  if(rr<=mid) return query(ls[o],l,mid,ll,rr);
  if(ll>mid) return query(rs[o],mid+1,r,ll,rr);
  return query(ls[o],l,mid,ll,rr)+query(rs[o],mid+1,r,ll,rr);
}
void dfs(int u,int fa){
  dep[u]=dep[fa]+1,siz[u]=1,rev[dfn[u]=++num]=u,Max=max(Max,dep[u]);
  for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    if(v^fa) dfs(v,u),siz[u]+=siz[v];
}
int main()
{
	int x,y;
	n=in(),m=in();
	for(int i=1;i<n;++i)
	  x=in(),y=in(),
	  add(x,y),add(y,x);
	num=0,dfs(1,0);
	for(int i=1;i<=n;++i) upd(rt[i],rt[i-1],1,Max,dep[rev[i]],siz[rev[i]]-1);
	while(m--){
	  x=in(),y=in();
	  ans=1ll*min(dep[x]-1,y)*(siz[x]-1);
	  if(dep[x]^Max){
		  ans+=query(rt[dfn[x]+siz[x]-1],1,Max,dep[x]+1,min(Max,dep[x]+y));
		  ans-=query(rt[dfn[x]],1,Max,dep[x]+1,min(Max,dep[x]+y));
		}
	  printf("%lld
",ans);
	}
  return 0;
}

以上是关于P3899 [湖南集训]谈笑风生的主要内容,如果未能解决你的问题,请参考以下文章

题解 P3899 [湖南集训]谈笑风生

P3899 [湖南集训]谈笑风生

luogu P3899 [湖南集训]谈笑风生

P3899 [湖南集训]谈笑风生 (线段树合并)

洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

[湖南集训] 谈笑风生 (主席树)