zoukankan      html  css  js  c++  java
  • HDU4348:To the moon

    浅谈主席树:https://www.cnblogs.com/AKMer/p/9956734.html

    浅谈标记永久化:https://www.cnblogs.com/AKMer/p/10137227.html

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4348

    相比一般的主席树,这个要多支持一个操作,那就是区间修改。我们不能把区间里的每一条链都建出来,因为那样时间空间都不允许,所以我们可以依靠标记永久化来实现。每次询问的时候,把一路上的标记全部累加起来,再计算对当前区间答案的影响就好了。

    时间复杂度:(O((n+m)logn))

    空间复杂度:(O((n+m)logn))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e5+5;
    
    char s[10];
    int n,m,tim;
    int a[maxn],rt[maxn];
    
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    struct tree_node {
        ll sum;
        int ls,rs,tag;
    };
    
    struct Chairman_tree {
        int tot;
        tree_node tree[maxn*30];
    
        void updata(int p) {
            tree[p].sum=tree[tree[p].ls].sum+tree[tree[p].rs].sum;
        }
    
        void build(int &now,int l,int r) {
            now=++tot;tree[now].tag=0;
            if(l==r) {
                tree[now].sum=a[l];
    			tree[now].ls=tree[now].rs=0;
                return;
            }
            int mid=(l+r)>>1;
            build(tree[now].ls,l,mid);
            build(tree[now].rs,mid+1,r);
            updata(now);
        }
    
        void change(int lst,int &now,int l,int r,int L,int R,int v) {
            now=++tot;tree[now]=tree[lst];
            tree[now].sum+=1ll*(min(r,R)-max(l,L)+1)*v;//记得要一路修改下去
            //如果调用updata函数用儿子节点更新自己的值,可能会用没被标记影响的上一个版本的主席树的儿子来更新自己
            if(L<=l&&r<=R) {
                tree[now].tag+=v;
                return;
            }
            int mid=(l+r)>>1;
            if(L<=mid)change(tree[lst].ls,tree[now].ls,l,mid,L,R,v);
            if(R>mid)change(tree[lst].rs,tree[now].rs,mid+1,r,L,R,v);
        }
    
        ll query(int now,int l,int r,int L,int R,int res) {
            if(L<=l&&r<=R)return tree[now].sum+1ll*(r-l+1)*res;
            int mid=(l+r)>>1;ll val=0;
            if(L<=mid)val+=query(tree[now].ls,l,mid,L,R,res+tree[now].tag);
            if(R>mid)val+=query(tree[now].rs,mid+1,r,L,R,res+tree[now].tag);
            return val;
        }
    }T;
    
    int main() {
        while(~scanf("%d%d",&n,&m)) {
            tim=T.tot=0;
            for(int i=1;i<=n;i++)
                a[i]=read();
            T.build(rt[0],1,n);
            for(int i=1;i<=m;i++) {
                scanf("%s",s+1);
                if(s[1]=='C') {
                    tim++;int l=read(),r=read(),d=read();
                    T.change(rt[tim-1],rt[tim],1,n,l,r,d);
                }
                else if(s[1]=='Q') {
                    int l=read(),r=read();
                    ll ans=T.query(rt[tim],1,n,l,r,0);
                    printf("%lld
    ",ans);
                }
                else if(s[1]=='H') {
                    int l=read(),r=read(),t=read();
                    ll ans=T.query(rt[t],1,n,l,r,0);
                    printf("%lld
    ",ans);
                }
                else if(s[1]=='B') {
                    int t=read();
                    tim=t;T.tot=rt[tim+1];
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    The test form is only available for requests from the local machine
    64位Win7下,先安装Visual Studio,后安装IIS的设置步骤
    [转] 如何在 64 位的 Windows 7 中安裝 PLSQL DEVELOPER 8 和 Oracle 11g x64 Client
    excel对csv的转义
    js中没有引用的匿名函数调用方法
    缓存实现条件
    js对象成员的删除特性 (delete)
    js语法作用域之间的相关性
    【转】UBOOT之四:uboot.lds分析
    linux C 中的volatile使用
  • 原文地址:https://www.cnblogs.com/AKMer/p/9967587.html
Copyright © 2011-2022 走看看