校赛的一道数据结构题(树状数组)

本文介绍了一道关于树状数组的复杂算法题,通过模拟小镇上的房屋价值变动和无敌破坏王拉尔夫可能造成的破坏,探讨了树状数组在高效处理区间更新和查询问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在此再写一道树状数组的题,算是巩固一下对数状数组的理解
比赛的时候还是太菜u了,没写对啊伤心
题目描述

​ 小镇上有一条nn个房子,一字排开。每个房子以及屋内物品的价值共为a_ia
i


​ 每个房子的价值会因为房主的关系有所浮动,总结一下有一下几种变化。
房主卖东西使价值降低。
房主买东西是价值提高。
房主卖房子换了个新房主,房屋价值就由新房主决定了。
​ 无敌破坏王拉尔夫(他有两个手)有mm个炸弹分别安装在小镇的不同地方,每个炸弹能炸毁L_iL
i

~R_iR
i

范围的房子。在某天,拉尔夫可能会出来破坏,每只手引爆一个炸弹。
​ 房主们作为有房子的土豪都很懒,每天只会有一个房主出来购物或卖房子。但是在拉夫尔可能出来破坏的那天大家都到外面避难,所以不会有购物或买卖的发生。
​ 现在预测了接下来kk天小镇可能发生的事情。请问在拉夫尔可能搞破坏的那一天,可能造成多大的经济损失?
输入解释

每个测试点有多组测试用例。
每个测试用例第一行包含n,m,kn,m,k,分别表示房屋数量和炸弹数量。
接下来11行有nn个整数,表示最开始每个房子的价值为a_ia
i


接下来mm行,每行有22个整数L_i,R_iL
i

,R
i

,代表第ii个炸弹能炸毁L_iL
i

~R_iR
i

的房子。
接下来kk行,表示接下来k天的每行按照一下格式表示四种行为。
1 x y,表示第11种行为,第xx间房子的房主购买了价值yy的物品放到房子里。
2 x y,表示第22种行为,第xx间房子的房主卖掉了房子里了价值yy的物品。
3 x y,表示第33种行为,第xx间房子的房主卖掉了房子。新房主入住后房子以及屋内物品的价值变为yy。
4 u v,表示第44种行为,假设拉尔夫出来进行破坏,引爆了第uu和第vv两个炸弹。
1\le n ,m,k\le 10^{5}1≤n,m,k≤10
5

1\le L_i,R_i,x \le n1≤L
i

,R
i

,x≤n
1\le a_{i},y\le 10^61≤a
i

,y≤10
6

u \neq vu


=v
1\le u,v\le m1≤u,v≤m
输出解释

对于每组测试用例针对第44种行为,输出拉尔夫可能会造成了多少损失。
输入样例

5 5 5
1 2 3 4 5
1 2
1 3
2 4
3 5
4 5
1 3 1
4 1 5
2 4 3
3 2 9
4 2 3
Copy
输出样例

Case #1:
12
15
Copy
提示

拉尔夫只是可能会造成损失,实际上并没有真正的进行破坏。拉尔夫也是个善良的人呀。
数据保证房屋及屋内物品的价值为非负整数。
在此附上Ac代码

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
ll sum[maxn];
ll a[maxn],L[maxn],R[maxn];
int n,m,k;
ll lowbit(int x)
{
    return x&(-x);
}
ll getsum(int x)
{
    ll ans = 0;
    for(;x;x-=lowbit(x)) ans += sum[x];
    return ans;
}
void update(int x,int v)
{
    for(;x <= n;x+=lowbit(x)) sum[x] += v;
}
int main()
{
    int kase = 0;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(sum,0,sizeof(sum));
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            update(i,a[i]);
        }
        for(int i = 1;i <= m;i++)
        {
            scanf("%d%d",&L[i],&R[i]);
        }
        printf("Case #%d:\n",++kase);
        for(int i = 1;i <= k;i++)
        {
            int op,x,y;
            cin >> op >> x >> y;
            if(op == 1)
            {
                a[x] += y;
                update(x,y);
            }
            else if(op == 2)
            {
                a[x] -= y;
                update(x,-y);
            }
            else if(op == 3)
            {
                int tmp = y - a[x];
                a[x] = y;
                update(x,tmp);
            }
            else if(op == 4)
            {
                ll ans =  0;
                int l1 = L[x],r1 = R[x],l2 = L[y],r2 = R[y];
                if(l1 > l2)
                {
                    swap(l1,l2);
                    swap(r1,r2);
                }
                if(r1 < l2)
                {
                   ans = getsum(r1) - getsum(l1 - 1);
                   ans += (getsum(r2) - getsum(l2 - 1));
                }
                else
                {
                    ans = getsum(max(r1,r2)) - getsum(l1 - 1);
                }
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值