gym101482K nwerc2014 Knapsack Collection

https://codeforces.com/gym/101482/

水題寫一年

離散化一下座標,假設排序後的座標是a[1],a[2],那麼[ a[1]+1 , a[2]]這一段區間的情況都是相同的,區別只是第一次收拾行李的時間不同,最大值肯定從某個a[i]+1開始,最小值肯定從某個a[i]開始,均值搞個等差數列求和就行了,每次取走一個後找下一個,我用的是線段樹上二分找下一個,O(n^2logn),寫了好久,還問了一下隊友怎麼寫,摸魚太久線段樹都不會了。。。然而學弟用的set,我沒想到= =,菜不成聲.jpg

#include<bits/stdc++.h>
using namespace std;

const int maxl=2010;

int n,s,t,cnt,tot;
long long mx,mi,pp,qq;
int a[maxl],b[maxl],ini[maxl],tmp[maxl];
struct node
{
	int l,r,sum;
}tree[maxl<<2];

inline void prework()
{
	scanf("%d%d%d",&n,&s,&t);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),b[i]=a[i];
	sort(b+1,b+1+n);
	tot=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
		ini[a[i]]++;
	}
}

inline void build(int k,int l,int r)
{
	tree[k].l=l;tree[k].r=r;
	if(l==r)
	{
		if(ini[l]>0)
			tree[k].sum=1;
		else
			tree[k].sum=0;
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}

inline int getsum(int k,int l,int r)
{
	int ret=0;
	if(l==tree[k].l && r==tree[k].r)
		return tree[k].sum;
	int mid=(tree[k].l+tree[k].r)>>1;
	if(r<=mid)
		ret=getsum(k<<1,l,r);
	else if(l>mid)
		ret=getsum(k<<1|1,l,r);
	else
	{
		ret=getsum(k<<1,l,mid);
		ret+=getsum(k<<1|1,mid+1,r);
	}
	return ret;
}

inline int findl(int k,int d,int now)
{
	if(tree[k].l==tree[k].r)
	{
		if(now+tree[k].sum>d)
			return tree[k].l;
		else
			return 0;
	}
	if(now+tree[k<<1].sum>d)
		return findl(k<<1,d,now);
	else
		return findl(k<<1|1,d,now+tree[k<<1].sum);
}

inline void dec(int k,int l)
{
	if(tree[k].l==tree[k].r)
	{
		tree[k].sum=0;
		return;
	}
	int mid=(tree[k].l+tree[k].r)>>1;
	if(l<=mid)
		dec(k<<1,l);
	else 
		dec(k<<1|1,l);
	tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}

inline void mainwork()
{
	long long sum,dd,len;
	int now,ind,nxt,d,last=0;
	for(int cas=1;cas<=tot;cas++)
	{
		now=b[cas];
		build(1,1,tot);sum=0;
		for(int i=1;i<=tot;i++)
			tmp[i]=ini[i];
		for(int i=1;i<=n;i++)
		{
			nxt=lower_bound(b+1,b+1+tot,now)-b;
			ind=0;
			if(nxt<=tot)
			{
				if(nxt>1)
					d=getsum(1,1,nxt-1);
				else d=0;
				ind=findl(1,d,0);
			}
			if(ind!=0)
				sum+=b[ind]-now;
			else
			{
				ind=findl(1,0,0);
				sum+=s-now+b[ind];
			}
			now=b[ind];
			tmp[ind]--;
			if(tmp[ind]==0)
				dec(1,ind);
			now=(now+t)%s;sum+=t;
		}
		if(cas==1)
			len=s-b[tot]+b[1];
		else
			len=b[cas]-last+1;
		if(cas==1)
			mx=len-1+sum,mi=sum,pp=len*sum+len*(len-1)/2;
		else
			mx=max(mx,len-1+sum),mi=min(mi,sum),pp+=len*sum+len*(len-1)/2;
		last=b[cas]+1;
	}
}

inline void print()
{
	printf("%lld\n%lld\n",mi,mx);
	qq=s;
	long long gcd=__gcd(pp,qq);
	pp/=gcd;qq/=gcd;
	printf("%lld/%lld",pp,qq);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章