zoukankan      html  css  js  c++  java
  • BZOJ 4765: 普通计算姬 (分块+树状数组)

    传送门

    解题思路

    树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响;对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是进与出之间的所有元素。分块后预处理出每个点修改对当前块多少个元素的影响f[i][j],再预处理出每个块的和,然后修改时利用f数组暴力扫一遍所有块,查询是大块直接查sum,小块用树状数组查。要开unsigned long long

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    
    using namespace std;
    const int MAXN = 100005;
    const int SIZE = 320;
    typedef unsigned long long ULL;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,m,val[MAXN],f[MAXN][SIZE],bl[MAXN],l[SIZE],r[SIZE],siz,num,rt;
    int head[MAXN],cnt,to[MAXN<<1],nxt[MAXN<<1],in[MAXN],out[MAXN],pos[MAXN];
    int dfn;
    ULL sum[MAXN],Sum[SIZE],ans,t[MAXN];
    
    inline void add(int bg,int ed){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
    }
    
    void update(int x,int y){
        for(;x<=n;x+=x&-x) t[x]+=y;
    }
    
    ULL query(int x){
        ULL ret=0;
        for(;x;x-=x&-x) ret+=t[x];
        return ret;
    }
    
    ULL Query(int x,int y){
        ULL ret=0;
        if(bl[x]==bl[y]) {
            for(register int i=x;i<=y;i++) ret+=query(out[i])-query(in[i]-1);
            return ret;
        }
        for(register int i=x;i<=r[bl[x]];i++) ret+=query(out[i])-query(in[i]-1);
        for(register int i=l[bl[y]];i<=y;i++) ret+=query(out[i])-query(in[i]-1);
        for(register int i=bl[x]+1;i<bl[y];i++) ret+=Sum[i];
        return ret;
    }
    
    void dfs(int x,int fa){
        in[x]=++dfn;pos[bl[x]]++;sum[x]=val[x];update(in[x],val[x]);
        for(register int i=1;i<=num;i++) f[x][i]=pos[i];
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];if(u==fa) continue;
            dfs(u,x);sum[x]+=sum[u];
        }
        out[x]=dfn;pos[bl[x]]--;Sum[bl[x]]+=sum[x];
    }
    
    int main(){
        n=rd(),m=rd();int op,x,y;
        siz=sqrt(n)+1;num=n/siz;if(n%siz) num++;
        for(int i=1;i<=n;i++) val[i]=rd(),bl[i]=(i-1)/siz+1;
        for(int i=1;i<=num;i++) l[i]=(i-1)*siz+1,r[i]=i*siz;
        r[num]=n;
        for(int i=1;i<=n;i++){
            x=rd(),y=rd();
            if(x==0 || y==0) rt=(x|y);
            else add(x,y),add(y,x);
        }
        dfs(rt,0);
        while(m--){
            op=rd(),x=rd(),y=rd();
            if(op==1){
                int now=y-val[x];
                for(register int i=1;i<=num;i++) 
                    Sum[i]+=(ULL)f[x][i]*now;
                update(in[x],y-val[x]);val[x]=y;
            }
            else printf("%llu
    ",Query(x,y));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    RedisTemplate使用事务处理
    maven命令学习
    springboot学习地址
    Mycat实现读写分离
    springboot-异步线程调用
    java多线程ExecutorService
    IntelliJ Idea 常用快捷键列表
    springMVC请求处理过程
    记录一次面试题
    java面试题-java内存模型
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9699747.html
Copyright © 2011-2022 走看看