BZOJ5194&&洛谷P4269 [USACO18FEB]Snow Boots G

版权声明:我这么弱的蒟蒻,虽然博文不是很好,但也请标明转发地址喵! https://blog.csdn.net/ACerAndAKer/article/details/82767714

假装是贪心

我们将地砖按照积雪厚度从大到小排序,靴子按照能踩的厚度从大到小排序,然后对于每双靴子,比较它能跑的长度与当前图中最长的连续一段厚度大于它的承受力的长度,若比 连续一段长,则能走完全程,如何找到连续一段?
我们用并查集,每次判断当前枚举到的地砖的dep是不是大于靴子的dep,因为两者都是从大到小枚举的,所以当前的都不会对之前产生影响,但是地砖深度 大于当前靴子,那么一定大于后面的靴子,所以我们把他标记一下,然后在原顺序中看他前面和后面是不是不能走,不能走就连起来,每次查询一下最长连续就好了
代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=1e5+5;
int n,m;
int fa[M],siz[M]; 
bool vis[M],ans[M];
struct tile{int de,id;}a[M];
struct boot{int de,di,id;}b[M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void write(int x)
{
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return ;
}
inline bool cmp1(tile x,tile y){return x.de>y.de;}
inline bool cmp2(boot x,boot y){return x.de>y.de;}
inline int find(int x)
{
	if (fa[x]!=x) return fa[x]=find(fa[x]);
	return x;	
} 
inline void unionn(int x,int y)
{
	siz[y]+=siz[x],fa[x]=y;
	return ;
}
signed main()
{
	n=read();m=read();
	for (int i=1;i<=n;i++) 
		fa[i]=i,siz[i]=1;
	for (int i=1;i<=n;i++) 
		a[i].de=read(),a[i].id=i;
	for (int i=1;i<=m;i++)
		b[i].de=read(),b[i].di=read(),b[i].id=i;
	sort(a+1,a+n+1,cmp1);
	sort(b+1,b+m+1,cmp2);
	int cnt=1,dis=0;
	for (int i=1;i<=m;i++)
	{
		while (cnt<=n&&a[cnt].de>b[i].de)
		{
			int x=a[cnt].id;vis[x]=1;
			if (vis[x-1]) unionn(x-1,x);
			if (vis[x+1]) unionn(x,find(x+1));
			dis=max(dis,siz[find(x)]);cnt++;
		}
		if (dis<b[i].di) ans[b[i].id]=1;
	}
	for (int i=1;i<=m;i++)
		write(ans[i]),puts("");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/82767714
今日推荐