hdu 1116 线段树或树状数组(基础题)

来源:互联网 发布:太阳能系统计算软件 编辑:程序博客网 时间:2024/06/06 12:57
题意: made in china
接下来,直接。。贴
1.线段树写法:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cctype>#include <sstream>#include <cmath>using namespace std;const int inf =0x3f3f3f3f;typedef long long LL;const int N = 1005;int ans;struct node{    int l, r, n;//n代表了区间的值,随题意而定} a[1000000];void buildtree(int l ,int r, int k)//建树的模板写法,通过递归和二分{    int mid;    if(l==r)    {        a[k].l=l;        a[k].r=r;        a[k].n=0;        return ;//递归终止条件    }    mid = (l+r) >> 1;    a[k].l=l;    a[k].r=r;    a[k].n=0;    buildtree(l,mid,k<<1);    buildtree(mid+1,r,k<<1|1);}void Insert(int n, int d, int k)//n为更新值, d为要更新的值{    int mid;    if(a[k].l==a[k].r&&a[k].l==d)//找到区间长度为一的,赋为n值    {        a[k].n+=n;        return ;    }    mid=(a[k].l+a[k].r)>>1;    if(mid>=d) Insert(n, d, 2*k);//这里的=必须要有,代表在左子树    else  Insert(n, d, 2*k+1);    a[k].n=a[2*k].n+a[2*k+1].n;//递归更新父节点的值}void Search(int l, int r, int k)//query{    int mid;    if(a[k].l==l&&a[k].r==r)    {        ans+=a[k].n;        return;    }    mid = (a[k].l+a[k].r)>>1;    if(r<=mid) Search(l, r, 2*k);//判断条件理解:such as(1, 3, 1) 原数组1,2,3,4,5     else if(l>mid) Search(l , r, 2*k+1);//k=1, mid=3 显然在左子树, such as(4, 5, 1)    else//显然在右子树中, 否则就将其分成俩部分分别求和    {        Search(l, mid, 2*k);        Search(mid+1, r, 2*k+1);    }}int main(){    int t, n, i, num, Case, a , b;    char str[10];    scanf("%d", &t);    for(Case=1;Case<=t;Case++)    {        scanf("%d", &n);        buildtree(1,n,1);        for(i=1; i<=n; i++)        {            scanf("%d", &num);            Insert(num,i,1);        }        printf("Case %d:\n", Case);        while(~scanf("%s", str))        {             if(strcmp(str, "End")==0)                break;            scanf("%d %d", &a, &b);            if(strcmp(str,"Add")==0) Insert(b, a, 1);            else if(strcmp(str,"Sub")==0) Insert(-b, a, 1);            else            {                ans = 0;                Search(a, b, 1);                printf("%d\n", ans);            }        }    }    return 0;}
2.树状数组写法:
#include <iostream>#include <algorithm>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <map>#include <set>using namespace std;#define lowbit(x)  (x&-x)#define  pii  pair<int,int>typedef long long  LL;const int N = 50010;int a[N];int n;void uptree(int i,int val){    while(i<=n)    {        a[i]+=val;        i+=i&-i;    }}int sum(int i){    int s=0;    while (i>0)    {        s+=a[i];        i-=i&-i;    }    return s;}int main(){    int t, k = 1, num;    char s[10];    int l, r;    scanf("%d", &t);    while(t--)    {        printf("Case %d:\n", k++);        scanf("%d", &n);        memset(a, 0, sizeof(a));        for(int i=1; i<=n; i++)        {            scanf("%d", &num);            uptree(i, num);        }        while(scanf("%s", s), strcmp(s, "End")!=0)        {            if(s[0]=='Q')            {                scanf("%d %d", &l, &r);                printf("%d\n", sum(r)-sum(l-1));            }            if(s[0]=='A')            {                scanf("%d %d", &l, &r);                uptree(l, r);            }            if(s[0]=='S')            {                scanf("%d %d", &l, &r);                uptree(l, -r);            }        }    }    return 0;}
0 0
原创粉丝点击