士兵杀敌(一)nyoj

来源:互联网 发布:站内优化 编辑:程序博客网 时间:2024/06/14 22:02
 这是一道很基础的线段树,用查询即可。
#include <iostream>
#include<algorithm>
#include <cstdio>
#include <cstring>
#define MAX 1000010
using namespace std;
int array[MAX];
int segTree[MAX * 4 + 10];      //线段树数组大小约为原数组大小的4倍
void build(int node, int begin, int end) {
    if(begin == end) {
        segTree[node] = array[begin];       //叶节点
    }
    else {
        build(node * 2, begin, (begin + end) / 2);
        build(node * 2 + 1, (begin + end) / 2 + 1, end);
        segTree[node] = segTree[node * 2] + segTree[node * 2 + 1];      //对两个孩子求和
    }
}
int query(int node, int begin, int end, int left, int right) {
    if(begin == left && end == right) {
        return segTree[node];
    }
    else {      //将区间一分为二,讨论三种情况
        int mid = (begin + end) / 2;
        if(right <= mid) return query(node * 2, begin, mid, left, right);
        else if(left > mid) return query(node * 2 + 1, mid + 1, end, left, right);
        else return query(node * 2, begin, mid, left, mid) + query(node * 2 + 1, mid + 1, end, mid + 1, right);  //查询区间和原始区间都要对半分。
    }
}
int main() {
    int N, M;
    scanf("%d %d", &N, &M);
    int i;
    for(i = 1; i <= N; i++) {
        scanf("%d", &array[i]);
    }
    build(1, 1, N);
    int left, right;
    while(M--) {
        scanf("%d %d", &left, &right);
        printf("%d\n", query(1, 1, N, left, right));
    }
    return 0;
}
        
0 0
原创粉丝点击