线段数(单点更新)

在第二场比赛中的k题用到了线段树,所以昨天和今天都在学习线段树,学习了线段树的单点更新以及查询,主要就是要建树、查询、更新,今天上午做了杭电上的1754,没想到今天下午的比赛就有这一道题,果断交了就a了。

先贴一下单点更新的及查询的模板:

<pre name="code" class="cpp">//最最基础的线段树,只更新叶子节点,然后把信息用PushUP(intr)这个函数更新上来
//1.bulid();
//2.query(a,b)
//3.update(a,b)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn=55555;
int sum[maxn<<2];
int n;
//根据题意做相关修改,询问时的操作
int operate(int a,int b) {
    return a+b;
}
void PushUp(int rt) {
    sum[rt] = operate(sum[rt<<1],sum[rt<<1|1]);
}
void bulid(int l=1,int r=n,int rt=1) {
    if(l==r) {
        //据题意做相关修改
        scanf("%d", &sum[rt]);
        return ;
    }
    int m = (l+r)>>1;
    bulid(lson);
    bulid(rson);
    PushUp(rt);
}
void update(int p, int add, int l = 1, int r = n, int rt=1) {
    if(l==r) {
        //据题意做相关修改
        sum[rt] += add;
        return ;
    }
    int m = (l+r)>>1;
    if(p <= m)
        update(p, add, lson);
    else
    update(p, add, rson);
    PushUp(rt);
}
int query(int L,int R,int l = 1,int r = n, int rt=1) {
    if(L<=l && r<=R) {
        return sum[rt];
    }
    int m = (l+r)>>1;
    int ret = 0;
    if(L <= m)
        ret = operate(ret, query(L,R,lson));
    if(R > m)
        ret = operate(ret, query(L,R,rson));
    return ret;
}

 

下面就是杭电的1754,也是第三场比赛的L题:

 
<a target=_blank href="http://http://vjudge.net/contest/view.action?cid=50696#problem/J">点击打开链接</a>,
题目大大意就是:给定一组学生成绩,要实现能查询其中的最高分并且能够更新其中的某一学生的值。把模板改一改就能完成了。
代码实现:
<pre name="code" class="cpp">#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define lson l, m , rt<<1
#define rson m+1, r, rt << 1 | 1

using namespace std;


int n, m;
int sum[200005<<2];

void build(int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%d", &sum[rt]);
        return ;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
}

void update(int p, int d, int l, int r, int rt)
{
    if(l == r)
    {
        sum[rt] = d;
        return ;
    }
    int m = (l+r)>>1;
    if(p<=m) update(p, d, lson);
    else update(p, d, rson);
    sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
}

int query(int ll, int rr, int l, int r, int rt)
{
    if(ll<=l && rr>=r)
        return sum[rt];
    int m = (l+r)>>1;
    int ans = 0;
    if(ll<=m) ans = max(ans, query(ll, rr, lson));
    if(rr>m) ans = max(ans, query(ll, rr, rson));
    return ans;
}

int main()
{
    int ma, a, b;
    char c[2];
    while(~scanf("%d%d", &n, &m))
    {
        memset(sum, 0, sizeof(sum));
        build(1, n, 1);
        for(int i = 0; i<m; i++)
        {
            scanf("%s%d%d", c, &a, &b);
            if(c[0]=='Q')
            {
                ma = query(a, b, 1, n, 1);
                printf("%d\n", ma);
            }
            if(c[0]=='U')
            {
                update(a, b, 1, n, 1);
            }
        }
    }
    return 0;
}


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值