版权声明:写得不好,随便转载,但请注明出处,感激不尽 https://blog.csdn.net/xyc1719/article/details/88383169
题目来源:CF1110F
【简要题意】给一棵有边权的树,已知各点编号的等于该点的dfs序。求对于每个vi,li,ri,求li到ri中到vi距离最小的叶子结点到vi的距离。
【分析】
暴力树形dp有70分就果断写完去搞T2,结果T2愣是没有结果。。。。
又是一道方便离线维护的题。和2月24日卡常数那道题颇为相似。考虑从u到v边权为c,显然有所有v的子树点距离-c,其余点距离+c,回溯也也是一个
的复杂度。然后处理询问时用线段树合并区间最小值。
当然也可以通过在线主席树做,这样两道题就更为相似了。
【code】
去掉O2也可以过,把vector换成链式前向星可以更快,std遍历最好用迭代器。
#pragma GCC optimize(2)
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=5e5+1000;
struct Edge{int v,c;};
vector<Edge>v[maxn];
struct Query{int l,r,id;};
vector<Query>q[maxn];int ans[maxn];
int bg[maxn],ed[maxn],dfs_clock;
int val[maxn];
int n,m;
void dfs(int u){
bg[u]=++dfs_clock;
for(vector<Edge>::iterator it=v[u].begin();it!=v[u].end();it++){
val[(*it).v]=val[u]+(*it).c;
dfs((*it).v);
}
ed[u]=dfs_clock;
if(bg[u]!=ed[u])val[u]=1LL<<60;
}
inline void read(int &x){
x=0;int fl=1;char tmp=getchar();
while(tmp<'0'||tmp>'9'){if(tmp=='-')fl=-fl;tmp=getchar();}
while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
}
struct Seg{
int l,r,val,tag;
}t[maxn<<2];
inline void update(int x){t[x].val=min(t[x<<1].val,t[x<<1|1].val);}
void build(int x,int l,int r){
t[x].l=l,t[x].r=r;
if(l==r){t[x].val=val[l];return ;}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
update(x);
}
inline void pushdown(int x){
if(!t[x].tag)return ;
t[x<<1].tag+=t[x].tag,t[x<<1|1].tag+=t[x].tag;
t[x<<1].val+=t[x].tag,t[x<<1|1].val+=t[x].tag;
t[x].tag=0;
}
void modify(int x,int l,int r,int val){
if(l<=t[x].l&&t[x].r<=r){
t[x].tag+=val,t[x].val+=val;
return ;
}
pushdown(x);
if(t[x<<1].r>=l)modify(x<<1,l,r,val);
if(t[x<<1|1].l<=r)modify(x<<1|1,l,r,val);
update(x);
}
int query(int x,int l,int r){
if(t[x].l>=l&&t[x].r<=r)return t[x].val;
pushdown(x);
int ret=1LL<<60;
if(t[x<<1].r>=l)ret=min(ret,query(x<<1,l,r));
if(t[x<<1|1].l<=r)ret=min(ret,query(x<<1|1,l,r));
return ret;
}
void solve(int u){
for(vector<Query>::iterator it=q[u].begin();it!=q[u].end();it++){
ans[(*it).id]=query(1,(*it).l,(*it).r);
}
for(vector<Edge>::iterator it=v[u].begin();it!=v[u].end();it++){
int V=(*it).v,c=(*it).c;
modify(1,1,n,c);
modify(1,bg[V],ed[V],-2*c);
solve(V);
modify(1,1,n,-c);
modify(1,bg[V],ed[V],2*c);
}
}
signed main(){
cin>>n>>m;
for(int i=2;i<=n;i++){
int x,y,c;y=i,read(x),read(c);
v[x].push_back((Edge){y,c});
}
dfs(1);
build(1,1,n);
for(int i=1;i<=m;i++){
int v,l,r;read(v),read(l),read(r);
q[v].push_back((Query){l,r,i});
}
solve(1);
for(int i=1;i<=m;i++){
printf("%lld\n",ans[i]);
}
return 0;
}