• BZOJ3188. [Coci 2011]Upit


    传送门

    有插入的操作,而且两种修改对区间和都可以打标记,所以直接平衡树维护就完事了

    区间加等差数列的操作就维护一个 $s,p$ 表示区间加以 $s$ 为首项,$p$ 为公差的数列,然后记得覆盖标记要直接把以前的标记都覆盖

    因为我不知道区间覆盖的值域是多少,所以多维护一个 $pd$ 判断是否有覆盖标记

    记得区间加等差数列的时候标记给右儿子的 $s$ 要变大

    下传标记我是在每次 $splay$ 之前先把整条链的标记传下来,打标记是把 $l-1$ 移到根,$r+1$ 移到根的右儿子

    标记打完要把根和根的右儿子的数据更新,因为会访问到 $0$ 和 $n+1$ 所以要多两个虚节点防止越界

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7;
    int n,m,a[N];
    int rt,c[N][2],fa[N],sz[N],cnt;
    ll val[N],sum[N];
    struct dat {
        ll c,s,p,pd;
        dat (ll _c=0,ll _s=0,ll _p=0,ll _pd=0) { c=_c,s=_s,p=_p,pd=_pd; }
        inline ll calc(int n) { return pd*c*n+s*n+1ll*n*(n-1)/2*p; }
        inline ll val(int n) { return pd*c+s+1ll*n*p; }
        inline dat operator + (const dat &tmp) const {
            if(tmp.pd) return dat(tmp.c,tmp.s,tmp.p,tmp.pd);
            return dat(c,s+tmp.s,p+tmp.p,pd);
        }
    }tag[N];
    inline void pushup(int x)
    {
        int &lc=c[x][0],&rc=c[x][1];
        sz[x]=sz[lc]+sz[rc]+1;
        sum[x]=sum[lc]+sum[rc]+val[x];
    }
    inline void pushdown(int x)
    {
        if(!x||(!tag[x].s&&!tag[x].p&&!tag[x].pd)) return;
        int &lc=c[x][0],&rc=c[x][1];
        if(tag[x].pd) sum[x]=0,val[x]=0;
        sum[x]+=tag[x].calc(sz[x]); val[x]+=tag[x].val(sz[c[x][0]]);
        if(lc) tag[lc]=tag[lc]+tag[x];
        tag[x].s+=tag[x].p*(sz[c[x][0]]+1);//
        if(rc) tag[rc]=tag[rc]+tag[x];
        tag[x]=dat(0,0,0,0);
    }
    inline void rotate(int x,int &k)
    {
        int y=fa[x],z=fa[y],d=(c[y][1]==x);
        y!=k ? c[z][c[z][1]==y]=x : k=x;
        fa[x]=z; fa[y]=x; fa[c[x][d^1]]=y;
        c[y][d]=c[x][d^1]; c[x][d^1]=y;
        pushup(y); pushup(x);
    }
    void push_tag(int x)
    {
        if(x!=rt) push_tag(fa[x]);
        else pushdown(x);
        pushdown(c[x][0]); pushdown(c[x][1]);
    }
    inline void splay(int x,int &k)
    {
        push_tag(x);
        while(x!=k)
        {
            int y=fa[x],z=fa[y];
            if(y!=k)
                (c[y][0]==x ^ c[z][0]==y) ? rotate(x,k) : rotate(y,k);
            rotate(x,k);
        }
    }
    inline int K_th(int k)
    {
        int x=rt;
        while(233)
        {
            if(sz[c[x][0]]+1==k) return x;
            if(sz[c[x][0]]>=k) x=c[x][0];
            else k-=sz[c[x][0]]+1,x=c[x][1];
        }
    }
    inline void split(int l,int r) { splay(K_th(l-1),rt); splay(K_th(r+1),c[rt][1]); }
    inline void Cover(int l,int r,ll v)
    {
        split(l,r); int x=c[c[rt][1]][0];
        tag[x]=tag[x]+dat(v,0,0,1); pushdown(x);
        pushup(fa[x]); pushup(rt);
    }
    inline void Add(int l,int r,ll p)
    {
        split(l,r); int x=c[c[rt][1]][0];
        tag[x]=tag[x]+dat(0,p,p,0); pushdown(x);
        pushup(fa[x]); pushup(rt);
    }
    inline void Ins(int k,ll v)
    {
        splay(K_th(k),rt); int f=K_th(k+1); splay(f,c[rt][1]);
        int &x=c[f][0]; x=++cnt;
        fa[x]=f; sz[x]=1; sum[x]=val[x]=v;
        pushup(f); pushup(rt);
    }
    inline void Query(int l,int r)
    {
        split(l,r); int x=c[c[rt][1]][0]; pushdown(x);
        printf("%lld
    ",sum[x]);
    }
    void build(int l,int r,int f)
    {
        int mid=l+r>>1;
        if(l<mid) build(l,mid-1,mid);
        if(mid<r) build(mid+1,r,mid);
        val[mid]=a[mid]; c[f][mid>f]=mid;
        fa[mid]=f; pushup(mid);
    }
    int main()
    {
        n=read(),m=read();
        for(int i=2;i<=n+1;i++) a[i]=read();
        cnt=n+2; build(1,n+2,0); rt=(n+3)>>1;
        int opt,a,b;
        for(int i=1;i<=m;i++)
        {
            opt=read(),a=read(),b=read();
            if(opt==1) { Cover(a+1,b+1,read()); continue; }
            if(opt==2) { Add(a+1,b+1,read()); continue; }
            if(opt==3) { Ins(a,b); continue; }
            Query(a+1,b+1);
        }
        return 0;
    }
  • 相关阅读:
    Qt 数据库篇
    js字符串函数(转)
    如何解决IE无法识别html5中的新标签(article、abbr、header等)
    web多页打印问题
    诡异的Spinner级联样式
    discuz x2用户删除了,帖子不能用了,恢复帖子的办法
    创业公司如何招聘优秀工程师
    清除目录下的SVN信息
    .NET 项目SVN 全局排除设置
    编程技术面试的五大要点
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11516196.html
Copyright © 2020-2023  润新知