【USACO 18 FEB】Snow Boots

【题目】

传送门

题目描述:

It’s winter on the farm, and that means snow! There are NN tiles on the path from the farmhouse to the barn, conveniently numbered 1 … n 1 \dots n 1n, and tile i is covered in f i f_i fi feet of snow. In his farmhouse cellar, Farmer John has b pairs of boots, numbered 1 … b 1 \dots b 1b. Some pairs are more heavy-duty than others, and some pairs are more agile than others. In particular, pair i lets FJ step in snow at most s i s_i si feet deep, and lets FJ move at most d i d_i di forward in each step.

Farmer John starts off on tile 1 and must reach tile n n n to wake up the cows. Tile 1 is sheltered by the farmhouse roof, and tile n n n is sheltered by the barn roof, so neither of these tiles has any snow. Help Farmer John determine which pairs of snow boots will allow him to make the trek.

输入格式:

The first line contains two space-separated integers n n n and b b b ( 1 ≤ n , b ≤ 1 0 5 1 \leq n,b \leq 10^5 1n,b105). The second line contains n n n space-separated integers; the ith integer is f i f_i fi , the depth of snow on tile i ( 0 ≤ f i ≤ 1 0 9 0 \leq f_i \leq 10^9 0fi109). It’s guaranteed that f 1 = f n = 0 f_1 = f_n = 0 f1=fn=0.

The next b b b lines contain two space-separated integers each. The first integer on line i + 2 i+2 i+2 is s i s_i si, the maximum depth of snow in which pair i can step. The second integer on line i + 2 i+2 i+2 is d i d_i di, the maximum step size for pair i. It’s guaranteed that 0 ≤ s i ≤ 1 0 9 0 \leq s_i \leq 10^9 0si109 and 1 ≤ d i ≤ n − 1 1 \leq d_i \leq n-1 1din1.

输出格式:

The output should consist of b lines. Line i should contain a single integer: 1 if Farmer John can trek from tile 1 to tile n wearing the ith pair of boots, and 0 otherwise.

样例数据:

输入
8 7
0 3 8 5 6 9 0 0
0 5
0 6
6 2
8 1
10 1
5 3
150 7

输出
0
1
1
0
1
1
1


【分析】

翻译就去洛谷上看吧,还是很清楚的

这道题有很多种解法啊,我用的是线段树

对于靴子 i i i ,我们将它能走的地方设为 1 1 1,不能走的地方设为 0 0 0 ,那么区间最长的连续的 0 0 0 的长度与 d i d_i di 相比就能得出答案,即如果这个值小于 d i d_i di,那么答案为 1 1 1;否则答案为 0 0 0

维护区间最长 0 0 0 的长度可以用线段树轻松解决,主要是怎么确定各个位置上是 0 0 0 还是 1 1 1 的问题

如果是每次枚举一只靴子都在线段树上找一遍来确定 0 , 1 0,1 0,1,那么总复杂度会是 n 2 log ⁡ 2 n n^2\log_2n n2log2n 的,显然不能通过

考虑先将线段树赋为全 0 0 0(都不能走),把雪和靴子按照雪的深度排序,从小到大开始扫描。如果扫到雪,则在线段树中把这块雪的位置改为 1 1 1(因为以后扫到的靴子能承受的积雪深度都不小于这块地砖的积雪深度,也就是都能走这块雪);如果扫到靴子,就统计最长连续的不能走的那段雪的数量,计算答案

线段树单点修改是 O ( log ⁡ 2 n ) O(\log_2n) O(log2n) 的,查询最长连续 0 0 0 的时间复杂度则是 O ( 1 ) O(1) O(1),总时间复杂度: O ( n log ⁡ 2 n ) O(n\log_2n) O(nlog2n)


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int n,b,ans[N];
struct snow{int s,d,op,id;}a[N<<1];
struct Tree{int L,R,num,len;}Seg[N<<4];
bool comp(const snow &p,const snow &q){return (p.s==q.s)?p.op<q.op:p.s<q.s;}
Tree pushup(Tree left,Tree right)
{
	Tree now;
	now.len=left.len+right.len;
	now.L=(left.L==left.len)?left.L+right.L:left.L;
	now.R=(right.R==right.len)?right.R+left.R:right.R;
	now.num=max(max(left.num,right.num),right.L+left.R);
	return now;
}
void build(int root,int l,int r)
{
	if(l==r)
	{
		Seg[root].L=Seg[root].R=Seg[root].num=Seg[root].len=1;
		return;
	}
	int mid=(l+r)>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	Seg[root]=pushup(Seg[root<<1],Seg[root<<1|1]);
}
void modify(int root,int l,int r,int x)
{
	if(l==r)
	{
		Seg[root].L=Seg[root].R=Seg[root].num=0;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid)  modify(root<<1,l,mid,x);
	else  modify(root<<1|1,mid+1,r,x);
	Seg[root]=pushup(Seg[root<<1],Seg[root<<1|1]);
}
int main()
{
	int n,b,i;
	scanf("%d%d",&n,&b);
	for(i=1;i<=n;++i)  scanf("%d",&a[i].s),a[i].op=0,a[i].id=i;
	for(i=1;i<=b;++i)  scanf("%d%d",&a[n+i].s,&a[n+i].d),a[n+i].op=1,a[n+i].id=i;
	sort(a+1,a+n+b+1,comp);
	build(1,1,n);
	for(i=1;i<=n+b;++i)
	{
		if(!a[i].op)  modify(1,1,n,a[i].id);
		else  ans[a[i].id]=(Seg[1].num+1<=a[i].d)?1:0;
	}
	for(i=1;i<=b;++i)
	  printf("%d\n",ans[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值