zoukankan      html  css  js  c++  java
  • [日常训练]普通计算姬

    Description

    给定一棵n个节点的带权树,节点编号为1-n,以root为根,设sum_{p}表示以点p为根的这棵子树中所有节点的权值和。支持下列两种操作:

    1.给定两个整数u,v,修改点u的权值为v
    2.给定两个整数l,r,计算$sum_{i=l}^{r}sum_{i}

    Input

    第一行两个整数n,m,表示树的节点数与操作次数。
    接下来一行n个整数,第i个整数d_{i}表示点i的初始权值。
    接下来n行每行两个整数a_{i},b_{i},表示一条树上的边,若a_{i}=0则说明b_{i}是根root
    接下来m行每行三个整数,第一个整数op表示操作类型。
    op=1则接下来两个整数u,v表示将点u的权值修改为v
    op=2则接下来两个整数l,r表示询问$sum_{i=l}^{r}sum_{i}

    Output

    对每个操作类型2输出一行一个整数表示答案。

    Sample Input

    6 4

    0 0 3 4 0 1

    0 1

    1 2

    2 3

    2 4

    3 5

    5 6

    2 1 2

    1 1 1

    2 3 6

    2 3 5

    Sample Output

    16

    10

    9

    HINT

    0$leq$d_{i},v<2^{31};1$leq$l$leq$r$leq$n;1$leq$u$leq$n

    Solution

    a_{i}分成k(sqrt{n}$leq$k$leq$sqrt{n}+1)个区间,每个区间的大小为sqrtnsqrt{n}。预处理出每个节点iroot路线上的所有节点所属分块j的总数t[i][j]。每次修改时只需修改每个分块的总值。每次询问时,只需算至多k个区间的和,以及至多2	imessqrt{n}a_{i}

    再记录每个节点的dfs序:fro[i]表示开始访问i节点的时间,beh[i]表示结束访问i节点的时间。dfs序对应的值记为key[;]。每次改变一个节点i的值时,在fro[i]之前(包括其自身)的所有key[i]值都加上v-a_{i}。再对dfs序用类似的方法进行分块,记录每个分块里的节点统一被改变的a_{i}值,记为s[;]。记fro[i]所属分块为frbeh[i]所属分块为be,则节点i的值为(s[fr]+key[fro[i])-(s[be]+key[beh[i])

    时间复杂度:O(n+sqrt{n}$	imes$n)

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define K 317
    #define N 100005
    #define M 200005
    using namespace std;
    typedef unsigned long long ll;
    struct graph{
        int nxt,to;
    }e[M];
    int g[N],f[N],n,m,cnt;
    ll a[N];bool v[N];
    /*==========================_d:dfs序    _n:编号==========================*/ 
    ll tot[N][K]/*每个点对应编号分块个数*/,s_d[K<<1],s_n[K]/*每个分块里的数字和*/,key[N<<1]/*dfs序单个值*/;
    int fro[N],beh[N],r_d,t_d=1,r_n,t_n;//s:分块总数,r:分块大小
    int n_n[N]/*序号所属分块*/,n_f[N]/*fro所属编号*/,n_b[N]/*beh所属编号*/;
    /*===============================read&write===============================*/ 
    inline int read(){
        int ret=0;char c=getchar();
        while(!isdigit(c))
            c=getchar();
        while(isdigit(c)){
            ret=ret*10+c-'0';
            c=getchar();
        }
        return ret;
    }
    inline ll read_ll(){
        ll ret=0;char c=getchar();
        while(!isdigit(c))
            c=getchar();
        while(isdigit(c)){
            ret=ret*10+c-'0';
            c=getchar();
        }
        return ret;
    }
    inline void write(ll k){
        if(!k) return;
        write(k/10);
        putchar(k%10+'0'); 
    }
    /*===============================ini_tree=================================*/ 
    inline void addedge(int x,int y){
        e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
    }
    inline void dfs(int u){
        int sta[N],top=0;
        cnt=0;v[u]=true;
        for(int i=g[u];i;i=e[i].nxt){
            v[e[i].to]=true;
            sta[++top]=e[i].to;
            ++tot[e[i].to][n_n[e[i].to]];
        }
        while(top){
            u=sta[top];fro[u]=++cnt;
            if(v[e[g[u]].to]){
                beh[u]=++cnt;--top;
                while(f[u]){
                    u=sta[top--];beh[u]=++cnt;
                }
            }
            else f[e[g[u]].to]=u;
            for(int i=g[u];i;i=e[i].nxt)
                if(!v[e[i].to]){
                    v[e[i].to]=true;
                    sta[++top]=e[i].to;
                    for(int j=1;j<=t_n;++j)
                        tot[e[i].to][j]=tot[u][j];
                    ++tot[e[i].to][n_n[e[i].to]];
                }
        }
    }
    /*==================================do===================================*/ 
    inline void change(int u,ll k){
    //    printf("k=%lld
    ",k);
        a[u]+=k;
        for(int i=1;i<=t_n;++i)
            s_n[i]+=tot[u][i]*k;
        for(int i=1;i<n_f[u];++i)
            s_d[i]+=k;
        if(n_f[u]*r_d==fro[u])
            s_d[n_f[u]]+=k;
        else for(int i=(n_f[u]-1)*r_d+1;i<=fro[u];++i)
            key[i]+=k;
    }
    /*=======================================================================*/ 
    inline void init(){
    /*==================read===================*/ 
        n=read();m=read();
        for(int i=1;i<=n;++i)
            a[i]=read_ll();
        for(int i=1,j,k;i<=n;++i){
            j=read();k=read();
            addedge(j,k);addedge(k,j);
        }
    /*================ini_tree=================*/
        r_n=sqrt(n);
        for(int i=1;i<=n;i+=r_n){
            ++t_n;
            for(int j=0;j<r_n&&i+j<=n;++j)
                n_n[i+j]=t_n;
        }
        dfs(0);
        r_d=sqrt(n<<1);t_d=((n<<1)+r_d-1)/r_d;
        for(int i=1;i<=n;++i){
            n_f[i]=(fro[i]+r_d-1)/r_d;
            n_b[i]=(beh[i]+r_d-1)/r_d;
        }
        for(int i=1;i<=n;++i){
            a[0]=a[i];a[i]=0;change(i,a[0]);
        }
    /*===================do====================*/
        int op,l,r,u;ll v,ans;
        while(m--){
            op=read();
            if(op==1){
                u=read();v=read_ll();
                change(u,v-a[u]);
            }
            else{
                l=read();r=read();ans=0;
                if(n_n[l]!=n_n[r]){
                    for(int i=n_n[l]+1;i<n_n[r];++i)
                        ans+=s_n[i];
                    if(l==(n_n[l]-1)*r_n+1) ans+=s_n[n_n[l]];
                    else for(int i=n_n[l]*r_n;i>=l;--i)
                        ans+=(s_d[n_f[i]]+key[fro[i]])-(s_d[n_b[i]]+key[beh[i]]);
                    if(r==n_n[r]*r_n) ans+=s_n[n_n[r]];
                    else for(int i=(n_n[r]-1)*r_n+1;i<=r;++i)
                        ans+=(s_d[n_f[i]]+key[fro[i]])-(s_d[n_b[i]]+key[beh[i]]);
                }
                else{
                    if(l==(n_n[l]-1)*r_n+1&&r==n_n[r]*r_n){
                        ans=s_n[n_n[l]];
                    }
                    else for(int i=l;i<=r;++i)
                        ans+=(s_d[n_f[i]]+key[fro[i]])-(s_d[n_b[i]]+key[beh[i]]);
                }
                if(!ans) putchar('0');
                else write(ans);
                putchar('
    ');
            }
        }
    }
    int main(){
        freopen("common.in","r",stdin);
        freopen("common.out","w",stdout);
        init();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    Sublime Text3添加到右键快捷菜单教程
    layui相关用法总结
    idea-----使用相关快捷键
    Redis相关语法
    idea-----怎样取消idea默认打开工程
    idea-----Idea在不关闭project的情况下进行Import Project
    Swagger2异常:Illegal DefaultValue null for parameter type integer java
    IntelliJ IDEA打jar时常遇见的问题
    Java的基本数据类型
    Java中对JSONArray中的对象进行排序
  • 原文地址:https://www.cnblogs.com/AireenYe/p/5831637.html
Copyright © 2011-2022 走看看