CF1073D Berland Fair 二分+线段树

考场上切的,挺简单的~

Code: 

#include <cstdio> 
#include <algorithm>  
#define N 200005 
#define inf 1000000004 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)    
using namespace std; 
ll arr[N]; 
struct Seg 
{ 
	#define lson (now<<1)
	#define rson (now<<1|1) 
	struct Node 
	{
		ll sum,minv;       
	}t[N<<2];  
	void pushup(int l,int r,int now) 
	{ 
		t[now].sum=0; 
		int mid=(l+r)>>1; 
		if(mid>=l) t[now].sum+=t[lson].sum, t[now].minv=t[lson].minv;   
		if(r>mid)  t[now].sum+=t[rson].sum, t[now].minv=min(t[now].minv, t[rson].minv);    
	}
	void build(int l,int r,int now) 
	{  
		if(l==r) 
		{
			t[now].sum=t[now].minv=arr[l]; 
			return; 
		}
		int mid=(l+r)>>1; 
		if(mid>=l) build(l,mid,lson);  
		if(r>mid)  build(mid+1,r,rson); 
		pushup(l,r,now); 
	}
	void update(int l,int r,int now,int p,ll v) 
	{
		if(l==r) 
		{
			t[now].sum=v; 
			t[now].minv=inf;       
			return; 
		}
		int mid=(l+r)>>1; 
		if(p<=mid) update(l,mid,lson,p,v); 
		else update(mid+1,r,rson,p,v);  
		pushup(l,r,now);   
	}
	ll query(int l,int r,int now,int L,int R) 
	{
		if(l>=L&&r<=R) return t[now].sum; 
		int mid=(l+r)>>1; 
		ll re=0; 
		if(L<=mid) re+=query(l,mid,lson,L,R); 
		if(R>mid)  re+=query(mid+1,r,rson,L,R); 
		return re;    
	} 
	#undef lson 
	#undef rson
}seg; 
int main() 
{
	// setIO("fairs");  
	int i,j,n,cnt; 
	ll k,tot=0; 
	scanf("%d%lld",&n,&k); 
	for(i=1;i<=n;++i) scanf("%lld",&arr[i]); 
	cnt=n; 
	seg.build(1,n,1);  
	while(1) 
	{ 
		int l=1,r=n,mid,ans=0; 
		while(l<=r) 
		{
			mid=(l+r)>>1;    
			if(seg.query(1,n,1,1,mid)<=k)
			{ 
				ans=mid,l=mid+1; 
			}
			else r=mid-1;    
		}   
		if(ans==n) 
		{   
			tot+=(k/seg.t[1].sum)*cnt;                            
			k-=(k/seg.t[1].sum)*seg.t[1].sum;      
		}
		else if(seg.t[1].minv>k) break;   
		else 
		{
			--cnt;   
			seg.update(1,n,1,ans+1,0);   
		} 
	}
	printf("%lld
",tot); 
	return 0; 
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11438676.html