CODEVS 1081 线段树练习 2

来源:互联网 发布:阿里云大厦 部门 编辑:程序博客网 时间:2024/05/16 15:15

题目描述 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

分析

水体随便写,就是第一次写树状数组,调了一段时间

代码

暴力

#include <bits/stdc++.h>#define N 100001int n,m;int a[N];int main(){    int t,x,y,z;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        scanf("%d",&t);        if(t==1)        {            scanf("%d %d %d",&x,&y,&z);            for(int j=x;j<=y;j++)                a[j]=a[j]+z;        }        else        {            scanf("%d",&x);            printf("%d\n",a[x]);        }    }}

线段树

#include <bits/stdc++.h>#define N 100005struct TREE{    int l,r,c,lazy;}t[N * 4];void build(int l,int r,int pos){    t[pos].l = l;    t[pos].r = r;    if (t[pos].l == t[pos].r)        return ;    int mid = (l + r) >> 1;    build(l,mid,pos * 2);    build(mid + 1,r,pos * 2 + 1);}void add(int num,int pos,int p){    if (t[p].l == t[p].r && t[p].r == pos)    {        t[p].c = num;        return ;    }    int mid = (t[p].l + t[p].r) >> 1;    if (pos > mid)        add(num,pos,p * 2 + 1);        else add(num,pos,p * 2);} void pushDown(int pos){    t[pos * 2 + 1].lazy += t[pos].lazy;    t[pos * 2].lazy += t[pos].lazy;    t[pos].lazy = 0;}void addSum(int l,int r,int c,int p){    if (t[p].l == l && t[p].r == r)    {        t[p].lazy += c;        return ;    }     int mid = (t[p].l + t[p].r) >> 1;    pushDown(p);    if (l > mid)        addSum(l,r,c,p * 2 + 1);        else        if (r <= mid)            addSum(l,r,c,p * 2);            else            {                addSum(l,mid,c,p * 2);                addSum(mid + 1,r,c,p * 2 + 1);            }}int find(int pos,int p){    if (t[p].l == t[p].r && t[p].r == pos)    {        return t[p].c + t[p].lazy;    }    pushDown(p);    int mid = (t[p].l + t[p].r) >> 1;    if (pos > mid)        return find(pos,p * 2 + 1);        else return find(pos,p * 2);}int main(){    int n,Q;    scanf("%d",&n);    build(1,n,1);    for (int i = 1; i <= n; i++)    {        int x;        scanf("%d",&x);        add(x,i,1);    }    scanf("%d",&Q);    for (int i = 1; i <= Q; i++)    {        int k;        scanf("%d",&k);        if (k == 1)        {            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            addSum(x,y,z,1);        }        else        {            int pos;            scanf("%d",&pos);            printf("%d\n",find(pos,1));        }    }}

树状数组

#include <bits/stdc++.h>int c[200000];int n,m,t,x,y,z;int lowbit(int x){    return x&-x;}void add(int x,int y){    while(x<=n)    {        c[x]=c[x]+y;        x=x+lowbit(x);    }}int getsum(int x){    int s=0;    while(x>=1)    {        s=s+c[x];        x=x-lowbit(x);    }    return s;}int main(){    scanf("%d",&n);    y=0;    for(int i=1;i<=n;i++)    {        scanf("%d",&x);        add(i,x-y);        y=x;    }    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        scanf("%d",&t);        if(t==1)        {            scanf("%d %d %d",&x,&y,&z);            add(x,z);            add(y+1,-z);        }        else        {            scanf("%d",&x);            printf("%d\n",getsum(x));        }    }}
0 0