树状数组,一个想法是当往p注水时,认为是其容量变小了,更新时二分枚举,注意一些优化。
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<utility> using namespace std; typedef long long LL; const int N = 200008; const LL INF = (LL)1 << (LL)61; #define MS(a, num) memset(a, num, sizeof(a)) #define PB(A) push_back(A) #define FOR(i, n) for(int i = 0; i < n; i++) LL C[N]; LL cap[N]; LL rem[N]; int n;//注意初始化n inline int lowbit(int x){ return x&-x; } inline void add(int x, LL val){ for(int i=x;i<=n;i+=lowbit(i)){ C[i] += val; } } inline LL sum(int x){//求1到x的和 LL ret = 0; for(int i=x;i>0;i-=lowbit(i)){ ret+=C[i]; } return ret; } int main(){ cin>>n; for(int i = 1;i <= n; i++){ scanf("%I64d", &cap[i]); rem[i] = cap[i]; add(i, cap[i]); } cap[n + 1] = INF; rem[n + 1] = INF; add(n + 1, INF); int m; cin>>m; int op, x,p , k; while(m--){ scanf("%d", &op); if(op == 1){ scanf("%d %d", &p, &x); int l = p, r = n +1; int ans = l; LL s = sum(p - 1); int start = p; while(l < r){ int mid = (l + r)>>1; LL s2= sum(mid) - s; if(s2 == 0){ start = mid + 1; } if(s2 < x){ l = mid + 1; }else{ r = mid; } } ans = l; LL s3 = sum(ans -1) - s; for(int i = start; i < ans ; i++){ if(rem[i]){ add(i, -rem[i]); rem[i] = 0; } } if(x - s3){ add(ans,-( x - s3)); rem[ans] -= x - s3; } }else{ scanf("%d", &k); printf("%I64d\n", cap[k] - rem[k]); } } return 0; }