zoukankan      html  css  js  c++  java
  • 【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
    ",ask(x));
        }
        return 0;
    }
  • 相关阅读:
    插入排序的算法分析
    SQL的UNION操作
    二分查找的思路
    怎么看吉他简谱
    一句CSS代码杜绝网站iframe挂马
    关于NewFolder.文件夹无法删除的办法
    C#监听USB接入
    C# 系统服务添加安装
    .NET 实现ISAPI过滤器,指定类型文件防下载
    ASP 简单的异或加密方法
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8383600.html
Copyright © 2011-2022 走看看