cf1073D Berland Fair (二分答案+树状数组)

用一个树状数组维护前缀和,每次我二分地找一个位置,使得我能一路买过去 但这个买不了

那以后肯定也都买不了了,就把它改成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\n",ans);
46     return 0;
47 }

 

posted @ 2018-10-27 22:23  Ressed  阅读(235)  评论(0编辑  收藏  举报