H - Skyscraper Gym - 102220H (树状数组)
题目链接:
https://cn.vjudge.net/problem/Gym-102220H
题目大意:
懒得写了。。。,自己翻译吧
具体思路:
将整个数组转换成差分数组之后,就会发现所求的答案 [ l , r ] 就是a[l] + (b[l+1] ~ b[r])这段区间中非负的值的总和。
AC代码:
1 #include<bits/stdc++.h> 2 #include<fstream> 3 #include<streambuf> 4 using namespace std; 5 # define ll long long 6 # define inf 0x3f3f3f3f 7 # define LL_inf (1ll<<60) 8 const int mod = 1e9+7; 9 const int maxn = 2e5+100; 10 const int maxstate= 1e6+100; 11 int a[maxn],b[maxn]; 12 ll tree_1[maxn],tree_2[maxn]; 13 int n,m; 14 int lowbit(int pos) 15 { 16 return pos&-pos; 17 } 18 void add1(int val,int pos)/// 区间修改,单点查询 19 { 20 while(pos<maxn) 21 { 22 tree_1[pos]+=val; 23 pos+=lowbit(pos); 24 } 25 } 26 void add2(int val,int pos) /// 单点修改,区间查询 27 { 28 while(pos<maxn) 29 { 30 tree_2[pos]+=val; 31 pos+=lowbit(pos); 32 } 33 } 34 ll ask1(int pos) 35 { 36 if(pos==0) 37 return 0; 38 ll sum=0; 39 while(pos) 40 { 41 sum+=tree_1[pos]; 42 pos-=lowbit(pos); 43 } 44 return sum; 45 } 46 ll ask2(int pos) 47 { 48 if(pos==0) 49 return 0; 50 ll sum=0; 51 while(pos) 52 { 53 sum+=tree_2[pos]; 54 pos-=lowbit(pos); 55 } 56 return sum; 57 } 58 int main() 59 { 60 int T; 61 scanf("%d",&T); 62 while(T--) 63 { 64 scanf("%d %d",&n,&m); 65 for(int i=0; i<=n; i++) 66 { 67 tree_1[i]=0; 68 tree_2[i]=0; 69 } 70 for(int i=1; i<=n; i++) 71 { 72 scanf("%d",&a[i]); 73 b[i]=a[i]-a[i-1]; 74 int tmp=b[i] >0 ? b[i] : 0; 75 add1(b[i],i); 76 add2(tmp,i); 77 } 78 while(m--) 79 { 80 int type; 81 scanf("%d",&type); 82 if(type==1) 83 { 84 int l,r,val; 85 scanf("%d %d %d",&l,&r,&val); 86 add1(val,l); 87 add1(-val,r+1); 88 if(b[l]<0) 89 { 90 int tmp=-b[l]; 91 if(tmp<val) 92 add2(val-tmp,l); 93 } 94 else if(b[l]>=0) 95 { 96 add2(val,l); 97 } 98 b[l]+=val; 99 100 if(b[r+1]>=0) 101 { 102 int tmp=min(b[r+1],val); 103 add2(-tmp,r+1); 104 } 105 b[r+1]-=val; 106 } 107 else if(type==2) 108 { 109 int l,r; 110 scanf("%d %d",&l,&r); 111 printf("%lld\n",ask2(r)-ask2(l)+ask1(l)); 112 } 113 } 114 } 115 return 0; 116 }