wannafly挑战赛4树的距离 离线处理,dfs序
Posted Billyshuai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wannafly挑战赛4树的距离 离线处理,dfs序相关的知识,希望对你有一定的参考价值。
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
wyf非常喜欢树。一棵有根数树上有N个节点,1号点是他的根,每条边都有一个距离,而wyf是个爱问奇怪问题的熊孩子,他想知道对于某个点x,以x为根的子树上,所有与x距离大于等于k的点与x的距离之和。
输入描述:
第一行一个正整数N
接下来N-1描述这棵树,每行两个数第i行两个数p和D表示树上有一条p到i+1长度为D的边。(p<=i)
下面一行一个正整数Q表示wyf的询问次数。
接下来Q行每行两个正整数x和k。 (1<=N,Q<=2x105,1<=D,K<=106)
输出描述:
对于每次询问x,k输出以x为根的子树上,所有与x距离大于等于k的点与x的距离之和。(若不存在这样的点,则输出应为0)
示例1
输入
3 1 2 1 3 2 1 3 1 2
输出
3 5
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+88;
long long ans[N];
int tot,head[N],pos[N],kt,lt[N];
struct cta{
int next,to,w;
}e[N<<1];
struct node{
int num,l,r;
long long sum;
}tr[N<<2];
struct qqq{
int id,rto;
long long k;
bool operator <(const qqq &A)const{
return k>A.k;
}
}qt[N];
struct ttt{
long long dis;
int id;
bool operator < (const ttt &B)const{
return dis>B.dis;
}
}dt[N];
void add(int u,int v,int w) {
e[tot].to=v;e[tot].next=head[u];e[tot].w=w;head[u]=tot++;
}
void build(int l,int r,int rt){
tr[rt].l=l,tr[rt].r=r;
tr[rt].sum=tr[rt].num=0;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void dfs(int u,long long now,int f){
pos[u]=++kt;
for(int i=head[u];~i;i=e[i].next) {
if(e[i].to==f) continue;
else dfs(e[i].to,dt[e[i].to].dis=e[i].w+now,u);
}
lt[u]=kt;
}
void modify(int pos,int rt,int cc){
int l=tr[rt].l,r=tr[rt].r;
int mid=(l+r)>>1;
if(l==r) {
tr[rt].num=1;
tr[rt].sum+=dt[cc].dis;
return;}
if(pos<=mid) modify(pos,rt<<1,cc);
else modify(pos,rt<<1|1,cc);
tr[rt].num=tr[rt<<1].num+tr[rt<<1|1].num;
tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
}
long long query(int L,int R,int rt,long long &cty){
long long now=0;
if(L>R) return 0;
int l=tr[rt].l,r=tr[rt].r;
if(L<=l&&R>=r) {cty+=tr[rt].num; return tr[rt].sum;}
int mid=(l+r)>>1;
if(mid>=L) now+=query(L,R,rt<<1,cty);
if(mid<R) now+=query(L,R,rt<<1|1,cty);
return now;
}
int tran[N];
int main(){
int n,x,y,m;
memset(head,-1,sizeof(head));
tot=kt=0;
scanf("%d",&n);
build(1,n,1);
for(int i=2;i<=n;++i) {
scanf("%d%d",&x,&y);
add(x,i,y);
add(i,x,y);
}
dfs(1,0,0);
for(int i=1;i<=n;++i) dt[i].id=i;
scanf("%d",&m);
for(int i=1;i<=m;++i) {
scanf("%d%lld",&qt[i].rto,&qt[i].k);
qt[i].id=i;
qt[i].k+=dt[qt[i].rto].dis;
}
sort(qt+1,qt+1+m);
sort(dt+1,dt+n+1);
int r=1;
for(int i=1;i<=n;++i) tran[dt[i].id]=i;
for(int i=1;i<=m;++i) {
long long now=0;
for(;r<=n;++r) if(!(dt[r].dis>=qt[i].k)) break;else modify(pos[dt[r].id],1,r);
ans[qt[i].id]=query(pos[qt[i].rto]+1,lt[qt[i].rto],1,now);
ans[qt[i].id]-=now*dt[tran[qt[i].rto]].dis;
}
for(int i=1;i<=m;++i) printf("%lld\\n",ans[i]);
}
以上是关于wannafly挑战赛4树的距离 离线处理,dfs序的主要内容,如果未能解决你的问题,请参考以下文章