codevs 1082 线段树练习 3 --分块练习

时间限制: 3 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

给你N个数,有两种操作:

1:给区间[a,b]的所有数增加X

2:询问区间[a,b]的数的和。

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,

再接下来一个正整数Q,每行表示操作的个数,

如果第一个数是1,后接3个正整数,

表示在区间[a,b]内每个数增加X,如果是2,

表示操作2询问区间[a,b]的和是多少。

pascal选手请不要使用readln读入

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 2 3

样例输出 Sample Output

9

数据范围及提示 Data Size & Hint

数据范围

1<=n<=200000

1<=q<=200000

分块大法 此题用分块优于线段树

屠龙宝刀点击就送

#include <ctype.h>
#include <cstdio>
#include <cmath>
#define N 500
typedef long long LL;
void read(LL &x)
{
    x=0;bool f=0;char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch==‘-‘) f=1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    x=f?(~x)+1:x;
}
LL C,m,belong[N*N],cnt,tag[N],sum[N],beg[N],en[N],n,a[N*N];
LL min(LL a,LL b) {return a>b?b:a;}
LL max(LL a,LL b) {return a>b?a:b;}
void update(LL x,LL y,LL z)
{
    for(LL i=belong[x];i<=belong[y];i++)
    {
        if(x<=beg[i]&&y>=en[i]) tag[i]+=z,sum[i]+=(en[i]-beg[i]+1)*z;
        else for(LL j=max(beg[i],x);j<=min(en[i],y);j++) a[j]+=z,sum[i]+=z;
    }
}
LL query(LL x,LL y)
{
    LL ans=0;
    for(LL i=belong[x];i<=belong[y];i++)
    {
        if(x<=beg[i]&&y>=en[i]) ans+=sum[i];
        else for(LL j=max(beg[i],x);j<=min(en[i],y);j++) ans+=a[j]+tag[i];
    }
    return ans;
}
int main()
{
    read(n);
    for(LL i=1;i<=n;i++) read(a[i]);
    C=sqrt(n);
    for(LL i=1;i<=n;i+=C)
    {
        beg[++cnt]=i;
        en[cnt]=min(i+C-1,n);
    }
    for(LL i=1;i<=cnt;i++)
    {
        for(LL j=beg[i];j<=en[i];j++) belong[j]=i,sum[i]+=a[j];
    }
    read(m);
    for(LL type,x,y,z;m--;)
    {
        read(type);
        read(x);
        read(y);
        if(type==1)
        {
            read(z);
            update(x,y,z);
        }
        else printf("%lld\n",query(x,y));
    }
    return 0;
}
时间: 2024-10-13 02:19:59

codevs 1082 线段树练习 3 --分块练习的相关文章

codevs 1082 线段树练习3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.

codevs 1082 线段树联系3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多

codevs 1082 线段树练习 3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.

【树状数组区间修改区间求和】codevs 1082 线段树练习 3

http://codevs.cn/problem/1082/ [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=2e5+2; 5 int n; 6 ll a[maxn]; 7 ll c1[maxn]; 8 ll c2[maxn]; 9 int lowbit(int x) 10 { 11 return x&-x; 12 } 13 void add(l

[Codevs] 1081 线段树练习 2 ----“分块!”

1081 线段树练习 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示

codevs 1082 线段树练习 3 区间更新+延迟标记

题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少. pascal选手请不要使用readln读入 输出描述 Output Description 对于每个询问输出一行

codevs 1082 线段树练习3 模板题

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 long long a[2000003],sum[10000003],add[10000003],n; 6 void pushup(long long rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} 7 void build(long long l,

[Codevs] 1080 线段树练习

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

1082 线段树练习 3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.