• OrzFAng系列–树 解题报告


    题目描述

    方方方种下了三棵树,两年后,第二棵树长出了n个节点,其中1号节点是根节点。

    给定一个n个点的树

    支持两种操作

    方方方进行m次操作,每个操作为:

    (1)给出两个数i,x,将第i个节点的子树中,与i距离为斐波那契数的节点权值+x(包括i本身)。

    (2)给出一个数i,求出第i个节点的子树中,与i距离为斐波那契数的节点的权值和(包括i本身)。

     

    题解

    斐波那契数列f_i=f_{i-1}+f_{i-2}

    首先这个会被操作的只有大概25层的节点。

    这样深度相同的区间在bfs序上是连续的区间,那么只要求出这样的左右端点是哪些,后面的就可以建个线段树|树状数组维护

    原来我觉得这样的区间很难求。其实只要类似倍增的做法Fa_{i,j}表示i的f_i次祖先。就可以直接求了。

    bfs序上的区间修改/查询 还可以用bit

    这类的玩意http://www.cnblogs.com/zzqsblog/p/5692627.html

    #include<map>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<complex>
    #include<iostream>
    #include<assert.h>
    #include<algorithm>
    using namespace std;
    #define inf 1001001001
    #define infll 1001001001001001001LL
    #define ll long long
    #define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
    #define gmax(a,b) (a)=max((a),(b))
    #define gmin(a,b) (a)=min((a),(b))
    #define Ri register int
    #define gc getchar()
    #define il inline
    il int read(){
        bool f=true;Ri x=0;char ch;while(!isdigit(ch=gc))if(ch=='-')f=false;while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}return f?x:-x;
    }
    #define gi read()
    #define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
    struct edge{
        int to,next;
    }e[501234];
    int last[123456],dep[123456],val[123456],f[123456][34],cnt,n,m;
    ll sum;
    il void link(int a,int b){
        e[++cnt]=(edge){b,last[a]};last[a]=cnt;
        e[++cnt]=(edge){a,last[b]};last[b]=cnt;
    }
    int lf[123456][34],rf[123456][34],bfn[123456],_bfn;
    // i的fib_i层的左&右 
    void dfs(int x,int fa=0){
        dep[x]=dep[fa]+1;
        f[x][1]=f[x][2]=fa;
        for(int i=3;i<=30;i++)f[x][i]=f[f[x][i-2]][i-1];
        for(int i=last[x];i;i=e[i].next){
            if(e[i].to!=fa){
                dfs(e[i].to,x); 
            }
        } 
    }
    bool vis[123456];
    void bfs(int s){
        memset(vis,0,sizeof(vis));
        queue<int>q;
        q.push(s);vis[s]=true;bfn[1]=++_bfn;
        while(!q.empty()){
            int c=q.front();q.pop();
            for(int i=last[c];i;i=e[i].next){
                if(!vis[e[i].to]){
                    q.push(e[i].to);
                    vis[e[i].to]=true;
                    bfn[e[i].to]=++_bfn;
                }
            }
        }     
    }
    void yuchuli(){
        dfs(1); 
        bfs(1);
        memset(lf,127,sizeof(lf));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=30;j++){
                int anc=f[i][j];
                if(!anc)break;
                gmin(lf[anc][j],bfn[i]);
                gmax(rf[anc][j],bfn[i]); 
            }
        } 
        for(int i=1;i<=n;i++)
            lf[i][1]=rf[i][1]=bfn[i];
    }
    namespace bit{
        ll a1[234567],a2[234567];
        ll qzh(int r){
            ll s1=0,s2=0;
            for(int i=r;i>=1;i-=i&-i) s1+=a1[i], s2+=a2[i];
            return (r+1)*s1-s2;
        }
        ll sum(int l,int r){
            return qzh(r)-qzh(l-1);
        }
        void edt(ll a,ll s1){
            ll s2=a*s1;
            for(;a<=n;a+=a&-a) a1[a]+=s1, a2[a]+=s2;
        }
        void edt(int l,int r,ll a) {edt(l,a); edt(r+1,-a);}
    }
    void _chg(int x,int y){
        for(int i=1;i<=30;i++){
            if(!rf[x][i])break;
            bit::edt(lf[x][i],rf[x][i],y);
        }
    }
    ll _qry(int x){
        sum=0;
        for(int i=1;i<=30;i++){
            if(!rf[x][i])break;
            sum=sum+bit::sum(lf[x][i],rf[x][i]);
        }
        return sum;
    } 
    int main(){
        //FO(tree2);
        n=gi;m=gi;
        for(int i=1;i<n;i++){
            int a,b;
            a=gi;b=gi;
            link(a,b);
        }
        yuchuli();
        while(m--){
            int op,x,y;
            op=gi;
            if(op==2){
                x=gi;
                printf("%I64d
    ",_qry(x)); 
            }
            if(op==1){
                x=gi;y=gi;
                _chg(x,y);
                //puts("");
            }
        }
    }
  • 相关阅读:
    Python利用Remove.bg接口自动消除图片背景
    解决ajxa跨域问题
    CentOS7 修改静态IP
    CentOS下 安装composer 与tp5.1
    centon 安装php-fpm+Nginx
    win10 安装selenium和使用
    Scrapy 爬虫框架入门
    Python 异常处理
    selenium和phantomjs的介绍
    MongoDB入门
  • 原文地址:https://www.cnblogs.com/chouti/p/5839713.html
Copyright © 2020-2023  润新知