【例题1】奶牛晒衣服
一道很基础的贪心,用大根堆维护当前状态下衣服湿度的最大值,然后让它减去 b b b,同时维护一个时间戳 t t t,判断 q . t o p ( ) − t × a > 0 q.top() - t \times a > 0 q.top()−t×a>0 是否成立即可。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define re register
#define rep(a,b,c) for(re int a(b) ; a<=c ; ++a)
#define drep(a,b,c) for(re int a(b) ; a>=c ; --a)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
priority_queue<int> q;
const int M = 5e5 + 10;
int n,a,b,x,t;
signed main(){
n = read(),a = read(),b = read();
rep(i,1,n) x = read(),q.push(x);
while(q.top() - t*a > 0){
int u = q.top();
q.pop();
u -= b;
q.push(u);
t++;
}
printf("%d\n",t);
return 0;
}
【例题2】雷达装置
一开始的思路是按左端点从小到大排序,然后记录下来当前的最大位置 p o s pos pos,每进入一个 a [ i ] . r a[i].r a[i].r 就和 p o s pos pos 比较,如果小就不管,大就更新。但如果有重叠的部分,只记录右端点,如果有两个小段,一个在中间,一个跨过了右端点,会让答案变小。
正确的贪心是按右端点升序排序,同样记录右端点 p o s pos pos,如果当前进入的 a [ i ] . l a[i].l a[i].l 和 a [ i ] . r a[i].r a[i].r 的区间包含 p o s pos pos,可以不管,否则记录能到的最大右端点。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define re register
#define rep(a,b,c) for(re int a(b) ; a<=c ; ++a)
#define drep(a,b,c) for(re int a(b) ; a>=c ; --a)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
const int M = 1e5+10;
int n;
double d;
struct node{
double l,r;
friend bool operator < (node a,node b) {
return a.r < b.r; }
}a[M];
signed main(){
n = read();
scanf("%lf",&d);
rep(i,1,n){
double x,y;
scanf("%lf%lf",&x,&y);
if(y > d) {
printf("-1\n"); return 0; }
a[i].l = 1.0 * (1.0 * x - 1.0 * sqrt(d*d - y*y));
a[i].r = 1.0 * (1.0 * x + 1.0 * sqrt(d*d - y*y));
}
sort(a+1,a+n+1);
int ans = 1;
double you = a[1].r;
rep(i,2,n){
if(a[i].l <= you && you <= a[i].r) continue;
ans++;
you = a[i].r;
}
printf("%d\n",ans);
return 0;
}
【例题3】畜栏预定
需要维护一个小根堆,存当前牛所在牛栏的编号和时间的右端点。每一次进来一头牛,把它的左端点和 q . t o p ( ) . r q.top().r q.top().r 比较