码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-05-06 11:55:40      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:tar   bool   main   date   href   区间   ble   输入   dev   

时间限制: 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;
}

 

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

标签:tar   bool   main   date   href   区间   ble   输入   dev   

原文地址:http://www.cnblogs.com/ruojisun/p/6815833.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!