HDU 1166 敌兵布阵 (我的树状数组加线段树点修改模板)

来源:互联网 发布:淘宝小铺名称能改吗 编辑:程序博客网 时间:2024/06/11 09:21

思路:本题因为是点修改,所以我们可以用线段树或者是树状数组了。线段树的基本操作我在我的代码中会具体体现,关键是要理解下面这幅图,具体的思想大家可以去看看其他的资料

线段树AC代码:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define N 50005int num[N];struct p{    int l,r,sum;}tree[4*N];void build(int root,int l,int r)    //root为当前所在节点的编号,l为它的左边界,r为它的右边界{    tree[root].l=l;    tree[root].r=r;    if(tree[root].l==tree[root].r)          //说明是叶子节点    {        tree[root].sum=num[l];        return ;    }    int mid=(l+r)/2;        //区间划分    build(root<<1,l,mid);   //左儿子    build(root<<1|1,1+mid,r);   //右儿子    tree[root].sum=tree[root<<1 ].sum+tree[root<<1|1].sum;  //当前节点值为两儿子之和}void update(int root,int pos,int val)   //因为要更新,所以我们要在根根节点root开始往下找{//pos为当前位置,val为需要更新成的值    if(tree[root].l==tree[root].r)    {        tree[root].sum=val;//找到了需要跟新的位置,更新它        return ;    }    int mid=(tree[root].l+tree[root].r)/2;    if(pos<=mid)    //左儿子        update(root<<1,pos,val);    else        update(root<<1|1,pos,val);      //右儿子    tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;}int query(int root,int L,int R) //root 表示根节点,[L,R]表示要查询的区间{    if(L<=tree[root].l&&R>=tree[root].r)            return tree[root].sum;          // [L,R]要查询的区间包含root 节点表示的区间直接返回root 节点的sum 值    int mid=(tree[root].l+tree[root].r)/2,ret=0;    if(L<=mid)ret+=query(root<<1,L,R);    if(R>mid)ret+=query(root<<1|1,L,R);    return ret;}int main(){    int t,j,n,a,b,i;    char str[10];    scanf("%d",&t);    for(j=1;j<=t;j++)    {        scanf("%d",&n);        for(i=1;i<=n;i++)            scanf("%d",&num[i]);        build(1,1,n);        printf("Case %d:\n",j);        while(1)        {            scanf("%s",str);            if(strcmp(str,"End")==0)                break;            scanf("%d %d",&a,&b);            if(str[0]=='Q')            {                if(a>b)swap(a,b);                printf("%d\n",query(1,a,b));            }            else if(str[0]=='A')            {                num[a]=num[a]+b;                update(1,a,num[a]);            }            else if(str[0]=='S')            {                num[a]=num[a]-b;                update(1,a,num[a]);            }        }    }    return 0;}


树状数组:

#include<string.h>#include<stdio.h>#include<math.h>int a[50005];int n;typedef __int64 ll;int lowbit(int t){    return t&(-t);//如果某个结点是左子节点,那么它的父节点的编号为i+lowbit(i)}                 //右子节点的父节点编号为i-lowbit(i)void insert(int t,int d){    while(t<=n)     //插入操作    {        a[t]+=d;        t=t+lowbit(t);    }}ll getsum(int t){    ll sum=0;    while(t>0)    {        sum+=a[t];        t=t-lowbit(t);    }    return sum;}int main(){    int T,i,j,k,t;    scanf("%d",&T);    for(t=1;t<=T;t++)    {        memset(a,0,sizeof(a));        scanf("%d",&n);        for(i=1;i<=n;i++)        {            scanf("%d",&k);            insert(i,k);        }       // getchar();        char str[10];        scanf("%s",str);        printf("Case %d:\n",t);        while(strcmp(str,"End")!=0)        {            int x,y;            scanf("%d %d",&x,&y);            if(strcmp(str,"Query")==0)                printf("%I64d\n",getsum(y)-getsum(x-1));            else if(strcmp(str,"Add")==0)                insert(x,y);            else if(strcmp(str,"Sub")==0)                insert(x,(-1)*y);            //getchar();            scanf("%s",str);        }    }    return 0;}


0 0
原创粉丝点击