Luogu P4392 [BOI2007]Sound 静音问题


Luogu P4392 [BOI2007]Sound 静音问题

解析

  • 挺简单的一道线段树题目,区间长度已经给定,只需用线段树处理区间最大、最小值,然后枚举区间左端点,判断这段区间是否合法即可

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=1e6+5;
int n,m,c,h[N];
bool flag;
struct Tree
{
	struct tree
	{
		int minn,maxx;
	}tr[N<<2];
	void pushup(int root)
	{
		tr[root].minn=min(tr[root*2].minn,tr[root*2+1].minn);
		tr[root].maxx=max(tr[root*2].maxx,tr[root*2+1].maxx);
		return;
	}
	void build(int root,int l,int r)
	{
		if(l==r)
		{
			tr[root].minn=tr[root].maxx=h[l];
			return;
		}
		int mid=(l+r)>>1;
		build(root*2,l,mid);
		build(root*2+1,mid+1,r);
		pushup(root);
		return;
	}
	int query(int root,int l,int r,int ll,int rr,int fag)
	{
		if(ll<=l&&r<=rr)
		{
			if(fag==1) return tr[root].minn;
			else return tr[root].maxx;
		}
		int mid=(l+r)>>1;
		if(mid>=rr) return query(root*2,l,mid,ll,rr,fag);
		else
		{
			if(mid<ll) return query(root*2+1,mid+1,r,ll,rr,fag);
			else
			{
				if(fag==1) return min(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
				else return max(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
			}
		}
	}
}str;
bool check(int x)
{
	int mins=str.query(1,1,n,x,x+m-1,1);
	int maxs=str.query(1,1,n,x,x+m-1,2);
	return (maxs-mins<=c)?1:0;
}
int main()
{
	scanf("%d%d%d",&n,&m,&c);
	for(int i=1;i<=n;i++) scanf("%d",&h[i]);
	str.build(1,1,n);
	for(int i=1;i<=n-m+1;i++)
	{
		if(check(i))
		{
			flag=1;
			printf("%d
",i);
		}
	}
	if(!flag) puts("NONE");
	return 0;
}
原文地址:https://www.cnblogs.com/Hawking-llfz/p/11599627.html