题目大意:
有一棵树,n个节点n-1条边,每个节点都有一个权值。然后m次查询输入x,y,a,b意思是从节点到x,y这条路径
上的所有权值在区间[a,b]内的权值和。
分析:自己大概想到了不会超时的方法,但是找不出代码错误。。。(先吧错误代码贴着。。)
int n,m;
int vis[N],val[N];
int son[N],sz[N],fa[N],fst[N],nxt[N<<1],to[N<<1],e;
int label;
int tid[N<<1],top[N],w[N<<2];
int dep[N];
void dfs(int u,int p){
fa[u]=p;
sz[u]=1;
for(int i=fst[u];~i;i=nxt[i]){
int v=to[i];
if(v==p)continue;
dep[v]=dep[u]+1;
dfs(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]){ son[u]=v; }
}
}
void dfs2(int u,int t){
vis[u]=1;
top[u]=t;
tid[u]=++label;
w[label]=val[u];
if(son[u])dfs2(son[u],t);
for(int i=fst[u];~i;i=nxt[i]){
int v=to[i];
if(!vis[v])dfs2(v,v);
}
}
int mi[N<<2],ma[N<<2],sum[N<<2];
void build(int ll,int rr,int i){
if(ll==rr){
sum[i]=mi[i]=ma[i]=w[ll];return ;
}
build(ll,md,ls),build(md+1,rr,rs);
mi[i]=min(mi[ls],mi[rs]);
ma[i]=max(ma[ls],ma[rs]);
sum[i]=sum[ls]+sum[rs];
}
int query(int ll,int rr,int l,int r,int i,int a,int b){
if(ll<=l&&r<=rr){
if(mi[i]>=a&&ma[i]<=b)return sum[i];
if(mi[i]>b||ma[i]<a)return 0;
//else return query(ll,md,l,md,ls,a,b)+query(md+1,rr,md+1,r,rs,a,b);
}
if(mi[i]>b)return 0;
if(ma[i]<a)return 0;
if(r<=md)return query(ll,md,l,md,ls,a,b);
else if(l>md) return query(md+1,rr,md+1,r,rs,a,b);
return query(ll,md,l,md,ls,a,b)+query(md+1,rr,md+1,r,rs,a,b);
}
int calc(int x,int y,int a,int b){
int ret=0;
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]])swap(x,y);
ret+=query(tid[top[y]],tid[y],1,n,1,a,b);
y=fa[top[y]];
}
if(x!=y){
if(dep[x]>dep[y])swap(y,x);
ret+=query(tid[x],tid[y],1,n,1,a,b);
}
else if(x==y){
if(val[x]>=a&&val[x]<=b)ret+=val[x];
}
return ret;
}
void init(){
dep[1]=sz[0]=0;label=0;
mem(son,0);mem(fst,-1);mem(vis,0);e=0;mem(vis,0);
}
inline void add(int u,int v){ to[e]=v;nxt[e]=fst[u];fst[u]=e++; }
int main(){
freopen("in.txt","r",stdin);
while(~sf("%d%d",&n,&m)){
init();
rep(i,1,n)sf("%d",&val[i]);
rep(i,1,n-1){
int u,v;sf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,1);
dfs2(1,1);
build(1,n,1);
while(m--){
int u,v,a,b;sf("%d%d%d%d",&u,&v,&a,&b);
pf("%d\n",calc(u,v,a,b));
}
}
}
另外,这题数据很水。。看到别人暴力都过了。。。
本文介绍了一种解决树状结构中特定路径上节点权值区间求和问题的算法实现。通过深度优先搜索预处理树形结构,并利用线段树进行区间查询优化,实现了高效的查询响应。
499

被折叠的 条评论
为什么被折叠?



