【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;
}

 

posted @ 2018-01-30 09:37  Konoset  阅读(210)  评论(0编辑  收藏  举报