單峰數列

D06發表於2024-07-28
  • 用線段樹維護原序列對應的差分陣列,可以把區間修改簡化為單點修改
點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
int a[100005],n;
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
struct t1
{
	int l,r;
	long long u,v,bj;
	bool fs,fu,fd;
	long long va;
}t[400005];
void update(int p)
{
	t[p].u=t[p*2].u;t[p].v=t[p*2+1].v;
	t[p].fu=(t[p*2].fu&&t[p*2+1].fu&&t[p*2].v<t[p*2+1].u);
	t[p].fd=(t[p*2].fd&&t[p*2+1].fd&&t[p*2].v>t[p*2+1].u);
	long long lv=t[p*2].va,rv=t[p*2+1].va;
	t[p].fs=(lv==rv&&t[p*2].fs&&t[p*2+1].fs);
	if(t[p].fs)
	{
		t[p].va=lv;
	}
	else
	{
		t[p].va=-1;
	}
}
void spread(int p)
{
	long long bj=t[p].bj;
	t[p].bj=0;
	t[p*2].bj+=bj;
	t[p*2+1].bj+=bj;
	t[p*2].u+=bj;t[p*2].v+=bj;
	t[p*2+1].u+=bj;t[p*2+1].v+=bj;
	if(t[p*2].fs)
	{
		t[p*2].va+=bj;
	}
	if(t[p*2+1].fs)
	{
		t[p*2+1].va+=bj;
	}
}
void build(int p,int l,int r)
{
	t[p].l=l;
	t[p].r=r;
	if(l==r)
	{
		t[p].va=t[p].u=t[p].v=a[l];
		t[p].fs=t[p].fu=t[p].fd=true;
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	update(p);
}
bool asks(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		return t[p].fs;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	bool va=true;
	long long lv,rv;
	if(l<=mid)
	{
		va=va&asks(p*2,l,r);
		lv=t[p*2].v;
	}
	if(r>mid)
	{
		va=va&asks(p*2+1,l,r);
		rv=t[p*2+1].u;
	}
	if(l<=mid&&r>mid)
	{
		va=va&(lv==rv);
	}
	return va;
}
bool asku(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		return t[p].fu;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	bool va=true;
	long long lv,rv;
	if(l<=mid)
	{
		va=va&asku(p*2,l,r);
		lv=t[p*2].v;
	}
	if(r>mid)
	{
		va=va&asku(p*2+1,l,r);
		rv=t[p*2+1].u;
	}
	if(l<=mid&&r>mid)
	{
		va=va&(lv<rv);
	}
	return va;
}
bool askd(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		return t[p].fd;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	bool va=true;
	long long lv,rv;
	if(l<=mid)
	{
		va=va&askd(p*2,l,r);
		lv=t[p*2].v;
	}
	if(r>mid)
	{
		va=va&askd(p*2+1,l,r);
		rv=t[p*2+1].u;
	}
	if(l<=mid&&r>mid)
	{
		va=va&(lv>rv);
	}
	return va;
}
void change(int p,int l,int r,int x)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		t[p].bj+=x;
		t[p].u+=x;
		t[p].v+=x;
		if(t[p].fs)
		{
			t[p].va+=x;
		}
	}
	else
	{
		spread(p);
		int mid=(t[p].l+t[p].r)>>1;
		if(l<=mid)
		{
			change(p*2,l,r,x);
		}
		if(r>mid)
		{
			change(p*2+1,l,r,x);
		}
		update(p);
	}
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		a[i]=read1();
	}
	build(1,1,n);
	int q;
	cin>>q;
	for(int i=1;i<=q;i++)
	{
		int opt,l,r;
		opt=read1();
		l=read1();
		r=read1();
		if(opt==1)
		{
			int x=read1();
			change(1,l,r,x);
		}
		else if(opt==2)
		{
			printf("%d\n",asks(1,l,r));
		}
		else if(opt==3)
		{
			printf("%d\n",asku(1,l,r));
		}
		else if(opt==4)
		{
			printf("%d\n",askd(1,l,r));
		}
		else if(opt==5)
		{
			int tl=l,tr=r;
			l++;
			r--;
			bool pd=true;
			while(l<r)
			{
				int mid=(l+r)>>1;
				bool pl=asku(1,tl,mid);
				bool pr=askd(1,mid,tr);
				if(pl==pr&&pr==true)
				{
					break;
				}
				else if(pl==true)
				{
					l=mid+1;
				}
				else if(pr==true)
				{
					r=mid-1;
				}
				else
				{
					pd=false;
					break;
				}
			}
			if(l>r)
			{
				pd=false;
			}
			else if(l==r)
			{
				pd=(asku(1,tl,l)&askd(1,r,tr));
			}
			printf("%d\n",pd);
		}
	}
	return 0;
}

相關文章