將近一年前寫的題目了 又翻出來看看
題目鏈接:H Skyscraper
思路:用線段樹維護差分數組
設b[i]=a[i]-a[i-1]
如果 bi<=0 說明在完成i-1時可以順便把i位置完成
如果 bi>0 說明完成i-1後至少還需要bi才能完成
那麼我們維護兩個樹狀數組
第一個樹狀數組維護的是差分數組 bi 第二個樹狀數組維護的是ci(ci=bi && bi>0)
修改操作就是常規的差分數組修改
詢問的話 就是
也就是
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
ll a[N],b[N];
ll p1[N],p2[N];
int n,m;
void add(int x,ll val,ll p[]){
while(x<=n){
p[x]+=val;
x+=x&-x;
}
}
ll query(int x,ll p[]){
ll ret = 0;
while(x){
ret+=p[x];
x-=x&-x;
}
return ret;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(p1,0,sizeof(p1));
memset(p2,0,sizeof(p2));
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
b[i]=a[i]-a[i-1];
add(i,b[i],p1);
if(b[i]>0) add(i,b[i],p2);
}
for(int i = 1; i <= m; i++){
int op,l,r,k;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
scanf("%d",&k);
add(l,k,p1),add(r+1,-k,p1);
if(b[l]>0) add(l,k,p2);
else if(b[l]+k>0) add(l,b[l]+k,p2);
if(b[r+1]>0){
if(b[r+1]-k>0) add(r+1,-k,p2);
else add(r+1,-b[r+1],p2);
}
b[l]+=k,b[r+1]-=k;
}else{
printf("%lld\n",query(l,p1)+query(r,p2)-query(l,p2));
}
}
}
return 0;
}