链接
https://www.luogu.org/problemnew/show/P1204
大意
有 n n 个时间段,个人,每个时间段都已一人挤奶(可能同时进行),每次挤奶有一人从 li l i 挤到 ri r i ,问最大有人挤奶时间段和无人挤奶时间段
思路
分两种(另外两种线段树和差分楼主是一个蒟蒻就不会做了)
洛谷评测记录截图
学校题库评测记录截图
两种算法的差距很明显
时空复杂度对比表
算法 | 时间复杂度 | 空间复杂度 |
---|---|---|
离散 | O(nlogn+n) O ( n l o g n + n ) | O(2n) O ( 2 n ) |
暴力 | O(max(r)−max(l)) O ( m a x ( r ) − m a x ( l ) ) | O(max(r)) O ( m a x ( r ) ) |
很明显当每次挤奶的时间太长时会超时而离散可以轻松通过,且暴力的空间开销明显更大
暴力代码
每次标记就行了
#include<cstdio>
#define min(a,b) (a)<(b)?(a):(b)
#define max(a,b) (a)>(b)?(a):(b)
using namespace std;
bool jmj[1000001];int x,y,n,l=50234567,r,ans1,ans2,f1,f2;
int main()
{
scanf("%d",&n);//输入
while(n--)
{
scanf("%d%d",&x,&y);
for(int i=x;i<y;i++) jmj[i]=1;l=min(x,l);r=max(y,r);//保存最大最小时间并标记
}
for(int i=l;i<r;i++)
if(jmj[i]) f1++,ans1=max(ans1,f1),f2=0;else f2++,ans2=max(ans2,f2),f1=0;//寻找
printf("%d %d",ans1,ans2);//输出
}
离散代码
开一个结构体维护答案就行了
#include<cstdio>
#include<algorithm>
#define r(i,a,b) for(int i=a;i<=b;i++)
#define o(a) (a.r-a.l)//o为此时间段的长度
using namespace std;int n,at,nat;
struct node
{
int l,r;
}k[5001],x;
bool cmp(node x,node y){return x.l<y.l;}//排序
int main()
{
scanf("%d",&n);//输入
r(i,1,n)
scanf("%d%d",&k[i].l,&k[i].r);//输入
sort(k+1,k+1+n,cmp);//排序
x=k[1];at=o(k[1]);nat=0;
r(i,2,n)
{
if(k[i].l<=x.r)
x.r=max(k[i].r,x.r) ;//若包含在内就直接更新
else//否则保存答案并更新新的时间段
{
at=max(at,o(x));//保存答案
nat=max(nat,k[i].l-x.r);//保存答案
x=k[i];//更新
}
}
printf("%d %d",at,nat);//输出
}