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;
}