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

codevs1082

时间:2018-03-14 22:04:09      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:block   style   tchar   bsp   query   lld   update   ++   git   

题目描述 Description

给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。

输入描述 Input Description

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

 

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

 

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

 

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

 

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

输出描述 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<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
int n,Q,a[200005];

inline int read(){
    char ch=getchar();int k=0,f=1;
    while(!isdigit(ch)) {if(ch==-) f=-1;ch=getchar();}
    while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-0;ch=getchar();}
    return k*f;
}

void add(int x,int add){
    for(;x<=n;x+=x&-x) a[x]+=add;
}

int query(int x){
    int k=0;for(;x;x-=x&-x) k+=a[x];return k; 
}

int main(){
    n=read();
    for(int i=1;i<=n;i++) add(i,read());
    Q=read();
    for(int i=1;i<=Q;i++){
        int flag=read(),x=read(),y=read();if(x>y)swap(x,y);
        if(flag==1){
            int z=read();
            add(x,(y-x+1)*z);add(y+1,-(y-x+1)*z);
        }
        else printf("%ld\n",query(y)-query(x-1));
    }
    return 0;
}

 

但打这题主要是为了理解树状数组的区间修改和区间查询(为啥我觉得树状数组比treap难多了,哪犇能教教我何时适用树状数组呢?)

 

#include<cstdio>
#include<cctype>
using namespace std;

long long c1[200004],c2[200004],n,q;

inline long long read(){
    char ch=getchar();long long k=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-0;ch=getchar();}
    return k;
}

void update(long long *arr,long long x,long long add){
    for(;x<=n;x+=x&-x) arr[x]+=add;
}

long long query(long long *arr,long long x){
    long long t=0;for(;x;x-=x&-x) t+=arr[x];return t;
}

int main(){
   n=read();long long las=0;
   for(long long i=1;i<=n;i++){
         long long y=read();update(c1,i,y-las);update(c2,i,(i-1)*(y-las));las=y;//i-1=n-(n-i+1)=>在前缀和中,y-las被加了(n-i+1)次,由于后来统计师算了n次,c[i]记录多算的数的大小 
   }
   q=read();
   for(long long i=1;i<=q;i++){
        long long flag=read(),l=read(),r=read();
        if(flag==1){
             long long inc=read();
             update(c1,l,inc);update(c1,r+1,-inc);//差分思想,c[i]记录差,则segma(c[1]~c[i])为数 i 的值 
             update(c2,l,(l-1)*inc);update(c2,r+1,-r*inc);//同理 l-1=n-(n-l+1) r=n-(n-(r+1)+1)
        }
    else{
        long long sum1=(l-1)*query(c1,l-1)-query(c2,l-1);
        long long sum2=r*query(c1,r)-query(c2,r);
        printf("%lld\n",sum2-sum1);
    }
   }
   return 0;
}

 

codevs1082

标签:block   style   tchar   bsp   query   lld   update   ++   git   

原文地址:https://www.cnblogs.com/MikuKnight/p/8570150.html

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