#include<cstdio> #include<algorithm> using namespace std; int a[1005]; int main(){ int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); sort(a+1,a+n+1); for(int i=1;i<n;++i) ans+=a[i+1]-a[i]-1; printf("%d",ans); return 0; }
#include<cstdio> typedef long long ll; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } int main(){ ll a,b,x,y,t; scanf("%lld%lld%lld%lld",&a,&b,&x,&y); t=gcd(x,y); x/=t; y/=t; double c1=(double)a/x,c2=(double)b/y; x=c1+1e-7,y=c2+1e-7; if(y<x) x=y; printf("%lld",x); return 0; }
题目大意:
某人每天工作时间m分钟,在a1,a2,...,an分钟 他可以休息,但是同一天任意两次休息必须间隔至少d分钟。问他至少需要多少天才能在每个可休息时间点都至少休息一次(就是说对于任意ai,总有一天在第ai分钟休息了)
解题思路:
a数组首先要排序
1.平衡树treap
首先把n个时间都放入treap中
第1天我们找出平衡树中最为靠前的那个,即a1,删除a1,然后在treap中找到a1+d的后继a',删除a',然后再找a'+d的后继...直到找不到,说明第一天结束。
然后第二天继续这样的操作,直到treap为空。
时间复杂度: 至少进行n次查找,treap中操作复杂度logn 所以为O(nlogn)
2.一个类似于队列的思想
ts[i]表示第i分钟在第ts[i]天休息了。
ans表示总共的天数,初值为1
设一个数组q,开始a1入队,ts[1]=1
然后从a2开始循环 i=2...n
对于ai如果它可以和q[t]同一天休息那么就++t,ts[i]=ts[q[t]];
否则q[t]=++ans;
最后q[++w]=i;
意思是q[t]一定是可接尾里时间最靠前的那个
#include<cstdio> #include<algorithm> using namespace std; const int N=2e5+5; struct X{ int a,id; bool operator<(const X &b){ return a<b.a; } }x[N]; int ts[N],q[N]; int rd(){ char c; while((c=getchar())<'0'||c>'9'); int re=c-'0'; while((c=getchar())>='0'&&c<='9') re=(re<<1)+(re<<3)+c-'0'; return re; } int main(){ int n=rd(),t=1,m=rd(),d=rd(),w=1,ans=1; for(int i=1;i<=n;++i) x[x[i].id=i].a=rd(); sort(x+1,x+n+1); ts[x[1].id]=q[1]=1; for(int j=2;j<=n;++j){ if(x[j].a-x[q[t]].a-1>=d) ts[x[j].id]=ts[x[q[t]].id],++t; else ts[x[j].id]=++ans; q[++w]=j; } printf("%d\n",ans); for(int i=1;i<=n;++i) printf("%d ",ts[i]); return 0; }