用一个树状数组维护前缀和,每次我二分地找一个位置,使得我能一路买过去 但这个买不了
那以后肯定也都买不了了,就把它改成0,再从头二分地找下一个位置,直到这一圈我可以跑下来
然后就看跑这一圈要花多少钱、能买多少糖,拿T除一除,减一减,再去跑下一圈
每个位置只会被删一次,所以复杂度是$O(nlog^2n)$的
但那个用树状数组再二分的过程 其实大概可以在线段树上分治来做到一个log,但我哪会啊
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=2e5+10,logn=70; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 ll N,T,a[maxn]; 16 ll c[maxn]; 17 18 inline int lowbit(int x){return x&(-x);} 19 inline void add(int x,ll y){ 20 for(;x<=N;x+=lowbit(x)) c[x]+=y; 21 } 22 inline ll query(int x){ 23 ll re=0;for(;x;x-=lowbit(x)) re+=c[x];return re; 24 } 25 26 int main(){ 27 //freopen(".in","r",stdin); 28 int i,j,k; 29 N=rd(),T=rd(); 30 for(i=1;i<=N;i++) 31 add(i,rd()); 32 k=0; 33 ll ans=0; 34 while(k<N){ 35 int l=1,r=N,t=0; 36 while(l<=r){ 37 int m=l+r>>1; 38 if(query(m)<=T) t=m,l=m+1; 39 else r=m-1; 40 } 41 if(t==N){ 42 ans+=T/query(t)*(N-k); 43 T%=query(t); 44 }else add(t+1,-query(t+1)+query(t)),k++; 45 }printf("%I64d ",ans); 46 return 0; 47 }