【贪心 + 模拟】UVA10382 Watering Grass

感觉这种位置指针跳来跳去的题好难写对,记录一下套路。

传送门:https://www.luogu.com.cn/problem/UVA10382

思路比较简单:处理一下每个装置的有效左右区间(显然半径刚好能够到达的点是临界),然后从左到右贪心地选取装置:具体来说就是维护一个前缀的控制区域(只需维护最右的端点),控制区域内是一个装置左边界的集合,我们从这个集合出发考察右边界的最大值,得到最大值后更新控制区域,如此下去即可。

while(cur<l){ // 只要控制区域的最右没有到达草坪的最右,就继续更新
	double np=cur; // new point 记录控制区域右端点。
	for(; p<=n && q[p].x<=cur; p++) np=max(np, q[p].y); // p 维护前缀点集的装置编号,np 从中更新最右点。
	
	if(np==cur && cur<l){ // 如果np没有得到更新而且无法到达终点,无解。
		ok=false;
		break;
	}
	
	res++; // 更新答案
	cur=np; // 更新控制区域
}
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define debug(x) cerr << #x << ": " << x << endl
#define pb(a) push_back(a)
#define set0(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define ceil(a,b) (a+(b-1))/b
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define ll_INF 0x7f7f7f7f7f7f7f7f
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;

#define x first
#define y second

inline void read(int &x) {
    int s=0;x=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=1e4+5;

int n, l;
double w;

PII e[N];
PDD q[N];

int main(){
	while(cin>>n>>l>>w && n){
		rep(i,1,n){
			int a, b; read(a), read(b);
			e[i]={b, a}; // radius and position
		}
		sort(e+1, e+1+n);
		
		rep(i,1,n){
			double o=e[i].y, r;
			if(e[i].x<=w/2) r=0;
			else r=sqrt(1.0*e[i].x*e[i].x-(1.0*w/2)*(w/2));
			double L=max((double)0, o-r), R=min((double)l, o+r);
			q[i]={L, R};	
		}
		
		sort(q+1, q+1+n);
		
		int res=0, p=1;
		bool ok=true;
		double cur=0;
		
		while(cur<l){ // 只要控制区域的最右没有到达草坪的最右,就继续更新
			double np=cur; // new point 记录控制区域右端点。
			for(; p<=n && q[p].x<=cur; p++) np=max(np, q[p].y); // p 维护前缀点集的装置编号,np 从中更新最右点。
			
			if(np==cur && cur<l){ // 如果np没有得到更新而且无法到达终点,无解。
				ok=false;
				break;
			}
			
			res++; // 更新答案
			cur=np; // 更新控制区域
		}
		
		if(ok) cout<<res<<endl;
		else puts("-1");
	}
	
    return 0;
}
posted @ 2021-07-11 12:01  HinanawiTenshi  阅读(34)  评论(0编辑  收藏  举报