zoj3279 ants 线段树

来源:互联网 发布:全智允新公司js 编辑:程序博客网 时间:2024/05/12 12:54

突然想学习一下线段树了,看了一下基本的知识,尝试了一道简单的线段树题目。

#include<iostream>#include<cstring>using namespace std;const int N = 100010;struct node {int sum;int l;int r;};struct node tree[4 * N]; //树数组长度需要区间长度的 4 倍int a[N];                //level即区间 void build(int t, int l, int r) { //建树,这里用数组存放树,类似的情况出现在堆排序中,节点 i 的左节点为 2*i,右节点 2*i + 1tree[t].l = l;                tree[t].r = r;      //根节点区间为 0-n,左子节点区间 0- n/2, 右子节点区间 n/2 - n, 左闭右开;if (l == r - 1) {   // 这里的区间 2-3(已经到叶子节点),即代表level 3, sum的数值表示此区间元素的数量tree[t].sum = a[l];     return;}int mid = (l + r) / 2;  //递归建左子树,递归建右子树,根sum的值为左右子树sun的和build(2 * t, l, mid);build(2 * t + 1, mid, r);tree[t].sum = tree[2 * t].sum + tree[2 * t + 1].sum;}void update(int t, int l, int r, int value) { //更新操作,从节点t开始更新, 将区间l-r的元素数量变为 valueif (tree[t].l >= l && tree[t].r <= r) {  //即改变level r中的元素个数tree[t].sum = value;return;}if (tree[t].l == tree[t].r - 1)return;int mid = (tree[t].l + tree[t].r) / 2;if (l <= mid) //如果根节点区间的中值 >= 区间l-r的左端update(2 * t, l, r, value); //那么在左子树中更新if (r > mid) //如果根节点区间的中值 < 区间l-r的右端update(2 * t + 1, l, r, value); //那么右子树也需要更新tree[t].sum = tree[2 * t].sum + tree[2 * t + 1].sum; //左右子树更新之后,更新根节点的sum值}int query(int t, int len) { //给定一个排名 len, 查询其处于哪一个levelif (tree[t].l == tree[t].r - 1) { //查找到区间, 返回levelreturn tree[t].r;}if (len <= tree[2 * t].sum) //如果排名 小于左子树元素数量,区间肯定在左子树中return query(2 * t, len);else //否则,在右子树查询排名为 (len - 左子树元素数量)的区间                      return query(2 * t + 1, len - tree[2 * t].sum);}int main(){int n;while (cin >> n) {for (int i = 0; i < n; ++i)cin >> a[i];memset(tree, 0, sizeof(tree));build(1, 0, n);int k;cin >> k;while (k--) {char type;cin >> type;if (type == 'p') {int level, num;cin >> level >> num;update(1, level - 1, level, num);}else {int len;cin >> len;cout<<query(1, len)<<endl;}}}    return 0;}


0 0
原创粉丝点击