在此再写一道树状数组的题,算是巩固一下对数状数组的理解
比赛的时候还是太菜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;
}