题解 P3114 【[USACO15JAN]Stampede S】
传送门
这里提供一种比较暴力的做法。
算法分析:离散化+区间覆盖。
根据题意,Farmer John 能看到奶牛的时候奶牛恰好经过
细节提示:
-
覆盖:当某一时间点已被覆盖,但新来的奶牛的
y 值更小时,需要更新原先的覆盖。 -
离散化:离散化时,不能使用左闭右闭的形式,应当使用左闭右开,否则容易引起冲突(先排序再离散化!)。
比如说:第一只奶牛占据的时间是 [1,2],
上代码:
#include<bits/stdc++.h>
#define rd(n) scanf("%lld",&n);
#define F(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
const int N=4e5+10;
long long n,p,v,x;
long long st[N],ed[N],t[N];
int c[N],d[N],y[N];
int main() {
rd(n)
F(i,1,n) {
rd(x)rd(y[i])rd(v)
x++;
x=-x;//将坐标转化为距离
st[i]=x*v;
ed[i]=st[i]+v-1;
t[++p]=st[i],t[++p]=ed[i];
t[++p]=ed[i]+1;//左闭右开
}
memset(c,0x3f,sizeof(c));
sort(t+1,t+p+1);//先排序再离散化
long long cnt=unique(t+1,t+p+1)-t-1;
F(i,1,n) {
st[i]=lower_bound(t+1,t+cnt+1,st[i])-t;//离散化
ed[i]=lower_bound(t+1,t+cnt+1,ed[i])-t;
F(j,st[i],ed[i]){//暴力覆盖
if(c[j]>y[i]){//如果覆盖这一段时间的奶牛的 y 值大于现在的奶牛,就更新
c[j]=y[i];//c 模拟时间轴上奶牛的 y 值
d[j]=i;//d 记录时间轴上的奶牛编号
}
}
}
int ans=0;
F(i,1,n) {
F(j,st[i],ed[i]) {
if(d[j]==i){
ans++;//如果第 i 头奶牛经过 y 轴的时间内能被看到,答案+1
break;
}
}
}
printf("%d",ans);
return 0;
}
AC记录
欢迎交流讨论,请点个赞哦~