# f816 TOI_Youtube
###### tags: `競程題解`,`競程`
Timestamp:2023/03/04 09:45
心得:想了好久 窩好笨QQ
想法:
對 d 做前綴和,對於一個 v_i 一定會有一個被刪掉的時候 它在 被加入~被刪掉(被扣到小於0) 這段期間,一定會被扣掉這段期間的所有 d
所以我把它變成差分的形式 在我把這個數加入的時候,記錄一個 cnt_j 代表目前在算到 j 的時候所有不小於 0 且大於 d_j 的數 (就可以直接扣掉 cnt_j * d_j)
那如果目前這個數介於 0~d_j 之間呢 那麼這個數對於 ans_j的貢獻就直接是 0 就好 但不是每一個 v_i 扣到最後都會剛剛好是 0
所以要在差分那邊動一點手腳 直接在差分的時候直接扣掉就好。
應該看扣就知道了~
```cpp=
#include "iostream"
using namespace std;
#define int long long
int ans[400010]={},cnt[400010]={};
int pre[400010]={},ary[400010]={},bonu[400010]={};
int n;
int sum(int l,int r){return pre[r]-pre[l-1];}
void fd(int pos){
int l = pos+1;
int r = l;
int add = (1<<30);
while(add){
if(r+add>n+1){
add/=2;
continue;
}
if(sum(l,r+add)>ary[pos]){
add/=2;
}
else{
r+=add;
}
}
// r -> max pos (full)
if(r==l&&ary[pos]<=sum(r,r)){
return ;
}
cnt[l]++;
cnt[r+1]--;
ans[l]+=ary[pos];
ans[r+1]-=ary[pos]-sum(l,r);
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
int k,s;
for(int i=1;i<=n;i++){
cin>>ary[i]>>s;
pre[i]=pre[i-1]+s;
}
pre[n+1]=pre[n];
for(int i=1;i<=n;i++)fd(i);
int now=0,ct=0;
for(int i=1;i<=n;i++){
now+=ans[i];
ct+=cnt[i];
now-=ct*sum(i,i);
cout<<now+bonu[i]+ary[i]<<"\n";
}
}
```