杭电多校-单峰数列-(线段树维护最值和标记)

单峰数列

题意:
对于一个整数数列,如果其先严格递增,然后在某一点后严格递减,我们称这个数列为单峰数列(严格递增和严格递减的部分均要是非空)。1<=n<=1e5,1<=a[i]<=1e9,1<=q<=1e5。
[l,r]都加上x,[l,r]是否全部相同,[l,r]是否为严格升序,[l,r]是否为严格降序,[l,r]是否为单峰数列。

思考:

代码:

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long 
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define node_l node<<1
#define node_r node<<1|1

using namespace std;
  
const int N = 1e5+10,mod = 998244353;

struct Node{
	int l,r;
	int minn,maxn;
	int laz;
	int up;
	int down;
}t[4*N];

int n,m;
int va[N];

void pushdown(int node)
{
	int laz = t[node].laz;
	if(laz!=0)
	{
		t[node_l].laz += laz;
		t[node_l].minn += laz;
		t[node_l].maxn += laz;
		t[node_r].laz += laz;
		t[node_r].minn += laz;
		t[node_r].maxn += laz;
		t[node].laz = 0;
	}
}

void pushup(int node)
{
	t[node].minn = min(t[node_l].minn,t[node_r].minn);
	t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
	int up = 0;
	up += t[node_l].up;
	up += t[node_r].up;
	up += (t[node_l].maxn<t[node_r].minn);
	int down = 0;
	down += t[node_l].down;
	down += t[node_r].down;
	down += (t[node_l].minn>t[node_r].maxn);
	t[node].up = (up==3);
	t[node].down = (down==3);
}

void build(int node,int l,int r)
{
	t[node].l = l,t[node].r = r;
	if(l==r)
	{
		t[node].minn = va[l];
		t[node].maxn = va[l];
		t[node].up = 1;
		t[node].down = 1;
		return ;
	}
	int mid = (t[node].l+t[node].r)>>1;
	build(node_l,l,mid);
	build(node_r,mid+1,r);
	pushup(node);
}

void update(int node,int l,int r,int value)
{
	if(t[node].l>r||t[node].r<l) return;
	if(t[node].l>=l&&t[node].r<=r)
	{
		t[node].laz += value;
		t[node].minn += value;
		t[node].maxn += value;
		return ;
	}
	pushdown(node);
	int mid = (t[node].l+t[node].r)>>1;
	if(l<=mid) update(node_l,l,r,value);
	if(r>mid) update(node_r,l,r,value);
	pushup(node);
}

int queryminn(int node,int l,int r)
{
	if(t[node].l>r||t[node].r<l)
	{
		return 1e18;
	}
	if(t[node].l>=l&&t[node].r<=r)
	{
		return t[node].minn;
	}
	pushdown(node);
	int mid = (t[node].l+t[node].r)>>1;
	if(r<=mid) return queryminn(node_l,l,r);
	else if(l>mid) return queryminn(node_r,l,r);
	else return min(queryminn(node_l,l,mid),queryminn(node_r,mid+1,r));
	pushup(node);
}

int querymaxn(int node,int l,int r)
{
	if(t[node].l>r||t[node].r<l)
	{
		return -1e18;
	}
	if(t[node].l>=l&&t[node].r<=r)
	{
		return t[node].maxn;
	}
	pushdown(node);
	int mid = (t[node].l+t[node].r)>>1;
	if(r<=mid) return querymaxn(node_l,l,r);
	else if(l>mid) return querymaxn(node_r,l,r);
	else return max(querymaxn(node_l,l,mid),querymaxn(node_r,mid+1,r));
	pushup(node);
}

int queryup(int node,int l,int r)
{
	if(t[node].l>=l&&t[node].r<=r)
	{
		return t[node].up;
	}
	pushdown(node);
	int mid = (t[node].l+t[node].r)>>1;
	if(r<=mid) return queryup(node_l,l,r);
	else if(l>mid) return queryup(node_r,l,r);
	else
	{
		int suc = 0;
		suc += queryup(node_l,l,mid);
		suc += queryup(node_r,mid+1,r);
		suc += (querymaxn(node_l,l,mid)<queryminn(node_r,mid+1,r));
		return (suc==3);
	}
	pushup(node);
}

int querydown(int node,int l,int r)
{
	if(t[node].l>=l&&t[node].r<=r)
	{
		return t[node].down;
	}
	pushdown(node);
	int mid = (t[node].l+t[node].r)>>1;
	if(r<=mid) return querydown(node_l,l,r);
	else if(l>mid) return querydown(node_r,l,r);
	else
	{
		int suc = 0;
		suc += querydown(node_l,l,mid);
		suc += querydown(node_r,mid+1,r);
		suc += (queryminn(node_l,l,mid)>querymaxn(node_r,mid+1,r));
		return (suc==3);
	}
	pushup(node);
}

signed main()
{
	IOS;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>va[i];
	build(1,1,n);
	cin>>m;
	while(m--)
	{
		int op,l,r,x;
		cin>>op>>l>>r;
		if(op==1)
		{
			cin>>x;
			update(1,l,r,x);
		}
		if(op==2)
		{
			if(queryminn(1,l,r)==querymaxn(1,l,r)) cout<<1<<"\n";
			else cout<<0<<"\n";
		}
		if(op==3)
		{
			if(queryup(1,l,r)) cout<<1<<"\n";
			else cout<<0<<"\n";
		}
		if(op==4)
		{
			if(querydown(1,l,r)) cout<<1<<"\n";
			else cout<<0<<"\n";
		}
		if(op==5)
		{
			int L = l,R = r;
			while(L<R)
			{
				int mid = (L+R+1)/2;
				if(queryup(1,l,mid)) L = mid;
				else R = mid-1;
			}
			int now = L;
			if(now==l||now==r)
			{
				cout<<0<<"\n";
				continue;
			}
			if(queryup(1,l,now)&&querydown(1,now,r)&&querymaxn(1,now,now)>queryminn(1,now+1,now+1)) cout<<1<<"\n";
			else cout<<0<<"\n";
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值