【Luogu】P3787冰精冻西瓜(线段树)
我脑子怕不是有坑qwqqq
用前缀和思想,dis[i]表示i离根的距离,那么修改操作其实是对x的子树区间加y/dis[x],查询的时候*dis[to]即可。
对付/0错的思路是建森林,然而这个地方我犯蠢了。
qwq。
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cctype> #include<cmath> #define left (rt<<1) #define right (rt<<1|1) #define mid ((l+r)>>1) #define lson l,mid,left #define rson mid+1,r,right #define maxn 2000020 #define eps 1e-8 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } struct Edge{ int next,to; double val; }edge[maxn*3]; int head[maxn],num; inline void add(int from,int to,double val){ edge[++num]=(Edge){head[from],to,val}; head[from]=num; } double tree[maxn*4]; double tag[maxn*4]; int dfn[maxn]; int root[maxn]; int father[maxn]; int top[maxn]; int son[maxn]; int deep[maxn]; int size[maxn]; double dis[maxn]; int tme,n,m; void unifnd(int x,int fa){ if(x==fa){ dis[x]=1; root[x]=x; } else root[x]=root[fa]; deep[x]=deep[fa]+1; size[x]=1; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(deep[to]) continue; if(fabs(edge[i].val)>eps){ father[to]=x; dis[to]=dis[x]*edge[i].val; unifnd(to,x); size[x]+=size[to]; if(son[x]==0||size[son[x]]<size[to]) son[x]=to; } else unifnd(to,to); } return; } void unionn(int x,int Top){ dfn[x]=++tme; top[x]=Top; if(son[x]==0) return; unionn(son[x],Top); for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==father[x]||to==son[x]) continue; if(edge[i].val==0) continue; unionn(to,to); } } inline void prepare(){ unifnd(1,1); for(int i=1;i<=n;++i) if(dfn[i]==0) unionn(root[i],root[i]); } inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; } void pushdown(int rt,int m){ if(fabs(tag[rt])<=eps) return; tag[left]+=tag[rt]; tag[right]+=tag[rt]; tree[left]+=tag[rt]*(m-(m>>1)); tree[right]+=tag[rt]*(m>>1); tag[rt]=0; } void update(int from,int to,double num,int l,int r,int rt){ if(from<=l&&to>=r){ tree[rt]+=num*(r-l+1); tag[rt]+=num; return; } pushdown(rt,r-l+1); if(from<=mid) update(from,to,num,lson); if(to>mid) update(from,to,num,rson); } double query(int o,int l,int r,int rt){ if(l==r) return tree[rt]; double ans=0; pushdown(rt,r-l+1); if(o<=mid) ans+=query(o,lson); else ans+=query(o,rson); return ans; } void add(int x,double num){ update(dfn[x],dfn[x]+size[x]-1,num/dis[x],1,n,1); return; } inline double ask(int x){ return query(dfn[x],1,n,1)*dis[x]; } int main(){ n=read(); for(int i=1;i<n;++i){ int x=read(),y=read(); double z; scanf("%lf",&z); add(x,y,z); add(y,x,z); } prepare(); m=read(); for(int i=1;i<=m;++i){ int opt=read(),x=read(); if(opt==1){ double y; scanf("%lf",&y); add(x,y); } else printf("%.8lf\n",ask(x)); } return 0; }