首页 > 代码库 > Codevs 1081 线段树练习2

Codevs 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, 表示询问第i个位置的数是多少。

输出描述 Output Description

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

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

数据范围

1<=n<=100000

1<=q<=100000

树状数组:(数据太弱,暴力都AC)

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int n,m,t[1000]; 6 void add(int k,int z) 7 { 8     while(k<=n) 9     {10         t[k]+=z;11         k+=k&(-k);12     }13 }14 int find(int x)15 {16     int ans=0;17     while(x)18     {19         ans+=t[x];20         x-=x&(-x);21     }22     return ans;23 }24 int main()25 {26     cin>>n;27     for(int i=1;i<=n;i++)28     {29         int x;30         cin>>x;31         add(i,x); 32     }33     cin>>m;34     for(int i=1;i<=m;i++)35     {36         int a,b,c,d,e,f;37         cin>>a;38         if(a==1) {39             cin>>d>>e>>f;40             for(int j=d;j<=e;j++)41               add(j,f);42         }43         if(a==2)44         {45             cin>>b;46             printf("%d\n",find(b)-find(b-1));47         }48     }49     50     return 0;51 }

用的是练习1的代码,稍加修改,加上数据太弱~~~~~~就AC啦~~

正解:(区间修改+单点查询)

技术分享
#include<iostream>#include<cstdio>#include<cstring>#define maxn 100010using namespace std;int n,m,a[maxn],t[maxn];void add(int k,int z){    while(k<=n)    {        t[k]+=z;        k+=k&(-k);    }}int find(int k){    int ans=0;    while(k)    {        ans+=t[k];        k-=k&(-k);    }    return ans;}int main(){    int i,j,k;    scanf("%d",&n);    for(i=1;i<=n;i++)      scanf("%d",&a[i]);    for(i=1;i<=n;i++)      add(i,a[i]-a[i-1]);    scanf("%d",&m);     for(i=1;i<=m;i++)    {        int x,y,z,w;        scanf("%d",&w);        if(w==1)        {            scanf("%d%d%d",&x,&y,&z);            add(x,z);            add(y+1,-z);        }        else        if(w==2)        {            scanf("%d",&x);            printf("%d\n",find(x));        }    }    return 0;}
View Code

思想 :t数组存放差分序列即a[i]-a[i-1],区间修改时 只需修改 两端点处的值即可【左端点加X,右端点减X】 单点查询时:输出从差分序列从1到i的和

 技术分享

 

图片有点烂,将就看吧

Codevs 1081 线段树练习2