hdu-1166 敌兵布阵

数据结构中的线段树处理的主要是一些对于区间的操作,比一般的方式要快很多(logn)

线段树的存储可以定义一个数据结构

struct segt{
     int rt;根节点
     int ls,rs//区间的左右端点
     int val ;//要维护的值
     /*其他*/        
}tree[maxn];

线段树是一种完全二叉树,用tree[ rt ] 存储的话 ,左儿子为 tree[ rt << 1 ] 右儿子为 tree[ rt << 1 | 1 ]

线段树将一个区间通过二分的方式逐渐的分成一些单元区间,每次划分维护 左右端点,根结点的值

每次操作是对这些单元区间进行操作

比如1到16吧,最初的区间根节点(rt)为1,最初的区间可以划分成左子树和右子树,

根结点分别为2(rt<<1)和3(rt<<1|1)代表的区间分别为 1 到 8 (rt = 2)和9到16(rt = 3),

1到8这个区间再继续划分,左子树根结点4,区间1到4,右子树根结点5,区间5到8,依次类推

直到每个区间只有一个数字

ac的代码

# include <cstdio>
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;

const int maxn=5e4+5;
int sum[maxn*4];

void build(int root,int l,int r){
    if(l==r) {
        scanf("%d",&sum[root]);
        return ;
    }
    build(root<<1,l,(l+r)/2);
    build(root<<1|1,(l+r)/2+1,r);
    sum[root]=sum[root<<1]+sum[root<<1|1];
}

void update(int p,int add,int l,int r,int root){
    if(l==r){
        sum[root]+=add;
        return;
    }
    if(p<=(l+r)/2) update(p,add,l,(l+r)/2,root<<1);
    else update(p,add,(l+r)/2+1,r,root<<1|1);
    sum[root]=sum[root<<1]+sum[root<<1|1];
}

int query(int L,int R,int l,int r,int root){
    if(L<=l&&r<=R) return sum[root];
    int cnt=0;
    if(L<=(l+r)/2) cnt+=query(L,R,l,(l+r)/2,root<<1);
    if(R>(l+r)/2) cnt+=query(L,R,(l+r)/2+1,r,root<<1|1);
    return cnt;
}

int main(){
    int t,l=0;
    scanf("%d",&t);
    while(l<t){
        int n;
        scanf("%d",&n);
        build(1,1,n);
        char qu[10];
        printf("Case %d:\n",++l);
        while(scanf("%s",qu)){
            if(qu[0]=='E') break;
            int a,b;
            scanf("%d %d",&a,&b);
            if(qu[0]=='A') update(a,b,1,n,1);
            if(qu[0]=='S') update(a,-b,1,n,1);
            if(qu[0]=='Q') {
                int ans=query(a,b,1,n,1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2017-04-28 19:11  林探惜  阅读(142)  评论(0编辑  收藏  举报