zoukankan      html  css  js  c++  java
  • cogs 1317. 数列操作C 区间修改 区间查询

    1317. 数列操作C

    ★★★   输入文件:shuliec.in   输出文件:shuliec.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【题目描述】

    假设有一个长度为 n(n100000) 的数列 A,支持如下两种操作:

    1. 将 Ai,Ai+1,,Aj 的值均增加 d

    2. 查询 As+As+1++At(st) 的值。

    根据操作要求进行正确操作并输出结果。

    【输入格式】

    第一行为一个正整数 n,表示数列的大小。

    第二行有 n 个整数,表示数列 A 各项的初始值。

    第三行为一个整数 m ,表示操作的个数。

    下面是 m 行,每行描述一个操作:

    ADD i j d(将 Ai,Ai+1,,Aj(1i,jn) 的值均增加一个整数 d

    SUM s t(表示查询 As++At 的值)

    【输出格式】

    对于每一次询问,输出查询到的结果。

    【样例输入】

    4
    1 4 2 3
    3
    SUM 1 3
    ADD 2 2 50
    SUM 2 3
    

    【样例输出】

    7
    56
    

    【提示】

    所有答案小于 4611686018427387904

    加强 10 组极限数据,未全部重测 by rvalue 2018.2.26

    还是线段树而已

    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=100005;
    #define ll long long
    ll a[maxn];
    int n,m;
    struct SegmentTree{
        int l,r;
        long long dat;
        long long lazy_tag;
    }t[maxn<<2];
    void Pushdown(int p,int l,int r,int mid){
        t[p*2].dat+=t[p].lazy_tag*(mid-l+1);
        t[p*2+1].dat+=t[p].lazy_tag*(r-mid);
        t[p*2].lazy_tag+=t[p].lazy_tag;
        t[p*2+1].lazy_tag+=t[p].lazy_tag;
        t[p].lazy_tag=0;
    }
    void build(int p,int l,int r){
        t[p].l=l;t[p].r=r;
        if(l==r){
            t[p].dat=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].dat=t[p*2].dat+t[p*2+1].dat;
    }
    ll Get(int p,int l,int r,int s,int tt){
        if(s>r||tt<l) return 0;
        if(s<=l&&r<=tt) return t[p].dat;
        int mid=(l+r)>>1;
        Pushdown(p,l,r,mid);
        return  Get(p*2,l,mid,s,tt)+ Get(p*2+1,mid+1,r,s,tt);
    }
    void Add(int p,int l,int r,int s,int tt,ll x){
        if(s>r||tt<l) return;
        if(s<=l&&r<=tt){
            t[p].dat+=x*(r-l+1);
            t[p].lazy_tag+=x;
            return;
        }
        int mid=(l+r)>>1;
        Pushdown(p,l,r,mid);
        Add(p*2,l,mid,s,tt,x);Add(p*2+1,mid+1,r,s,tt,x);
        t[p].dat=t[p*2].dat+t[p*2+1].dat;
    }
    int main()
    {
        freopen("shuliec.in","r",stdin);freopen("shuliec.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        scanf("%d",&m);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            string s;cin>>s;
            if(s[0]=='S'){
                int l,r;scanf("%d%d",&l,&r);
                printf("%lld
    ",Get(1,1,n,l,r));    
            }
            else{
                int s,t;
                ll d;
                scanf("%d%d%lld",&s,&t,&d);
                Add(1,1,n,s,t,d);
            }
        }
        
        
        return 0;
     } 

     还有一个

    标记永久化线段树

    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    const int maxn=100005;
    #define LL long long
    #define mid (l+r>>1)
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define lson ls,l,mid
    #define rson rs,mid+1,r
    int n,m,cnt,a[maxn];
    LL sum[maxn<<2],lazy[maxn<<2];
    void Build(int rt,int l,int r){
        if(l==r){
            sum[rt]=a[l];
            return;
        }
        Build(lson),Build(rson);
        sum[rt]=sum[ls]+sum[rs];
    }
    void Add(int rt,int l,int r,int s,int t,LL qx){
        if(s>r||t<l)return;
        if(s<=l&&r<=t){
            lazy[rt]+=qx;
            sum[rt]+=qx*(r-l+1);
            return;
        }
        Add(lson,s,t,qx),Add(rson,s,t,qx);
        sum[rt]=sum[ls]+sum[rs]+lazy[rt]*(r-l+1);
    }
    LL Get(int rt,int l,int r,int s,int t){
        if(s>r||t<l)return 0;
        if(s<=l&&r<=t)return sum[rt];
        int ll=max(l,s),rr=min(r,t);
        return lazy[rt]*(rr-ll+1)+Get(lson,s,t)+Get(rson,s,t);
    }
    int main(){
        freopen("shuliec.in","r",stdin);freopen("shuliec.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        Build(1,1,n);
        scanf("%d",&m);
        for(int i=0;i<m;i++){
            char s[10];
            scanf("%s",s);
            if(s[0]=='S'){
                int l,r;scanf("%d%d",&l,&r);
                printf("%lld
    ",Get(1,1,n,l,r));
            }
            else{
                int l,r;LL x;scanf("%d%d%lld",&l,&r,&x);
                Add(1,1,n,l,r,x);
            }
        }
    }

     标记永久化就是在打标记的时候只需要打在上面就行了

    不需要往下放

  • 相关阅读:
    二次离线莫队
    一些不等积分的练习(持续更新)
    杂题20210427
    杂题20210415
    杂题20210203
    php pack()函数详解与示例
    SHOI2020抱灵祭
    BJOI2021游记+题解
    博客搬家
    听课记录 210220【分治,树分治,CDQ分治】
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11307395.html
Copyright © 2011-2022 走看看