【JZOJ3236】矮人排队

description

在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏。白雪公主决心终结这样的生活,所以为他们举办了体育课。 在每节课开始时,矮人必须按他们的身高站队。假定矮人们有高度1,2,...,N(每个人高度互不相同)。然而,由于不健康的生活方式,矮人的智力有所恶化,所以他们没有能力依照自己的高度排序。

因此,白雪公主发出以下形式命令帮助他们:

1 X Y:X和Y位置的矮人互换位置。

2 A B:询问高度为A,A+1,..., B的矮人(不一定是按照这个顺序)是否已形成了当前队列的连续子序列。

帮助矮人按照白雪公主的指示行动,并回答她的问题。


analysis

  • 裸的线段树

  • 线段树叶子节点下标储存该节点高度的人的位置

  • 查询一段高度即查询该区间内位置编号最大与最小的差是否为区间大小

  • 打得有点丑,但跑的快


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 200005
#define reg register int
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

int mn[MAXN*4],mx[MAXN*4],val[MAXN*4];
int a[MAXN],b[MAXN],c[MAXN];
int n,m;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void build(int t,int l,int r)
{
	if (l==r)
	{
		mn[t]=mx[t]=val[t]=b[l];
		return;
	}
	int mid=(l+r)>>1;
	build(t<<1,l,mid),build((t<<1)+1,mid+1,r);
	mn[t]=min(mn[t<<1],mn[(t<<1)+1]);
	mx[t]=max(mx[t<<1],mx[(t<<1)+1]);
}
inline int query_max(int t,int l,int r,int x,int y)
{
	if (l==x && y==r)return mx[t];
	int mid=(l+r)>>1;
	if (y<=mid)return query_max(t<<1,l,mid,x,y);
	else if (x>mid)return query_max((t<<1)+1,mid+1,r,x,y);
	else return max(query_max(t<<1,l,mid,x,mid),query_max((t<<1)+1,mid+1,r,mid+1,y));
}
inline int query_min(int t,int l,int r,int x,int y)
{
	if (l==x && y==r)return mn[t];
	int mid=(l+r)>>1;
	if (y<=mid)return query_min(t<<1,l,mid,x,y);
	else if (x>mid)return query_min((t<<1)+1,mid+1,r,x,y);
	else return min(query_min(t<<1,l,mid,x,mid),query_min((t<<1)+1,mid+1,r,mid+1,y));
}
inline int query_pos(int t,int l,int r,int x)
{
	if (l==r)return t;
	int mid=(l+r)>>1;
	if (x<=mid)return query_pos(t<<1,l,mid,x);
	else return query_pos((t<<1)+1,mid+1,r,x);
}
int main()
{
	//freopen("T1.txt","r",stdin);
	n=read(),m=read();
	fo(i,1,n)a[i]=read(),b[a[i]]=i;
	build(1,1,n);
	while (m--)
	{
		int z=read(),x=read(),y=read();
		if (z==1)
		{
			int xx=a[x],yy=a[y];
			swap(a[x],a[y]);
			int tmpx=query_pos(1,1,n,xx),tmpy=query_pos(1,1,n,yy);
			swap(val[tmpx],val[tmpy]);
			mx[tmpx]=mn[tmpx]=val[tmpx],mx[tmpy]=mn[tmpy]=val[tmpy];
			tmpx>>=1,tmpy>>=1;
			while (tmpx)mx[tmpx]=max(mx[tmpx<<1],mx[(tmpx<<1)+1]),mn[tmpx]=min(mn[tmpx<<1],mn[(tmpx<<1)+1]),tmpx>>=1;
			while (tmpy)mx[tmpy]=max(mx[tmpy<<1],mx[(tmpy<<1)+1]),mn[tmpy]=min(mn[tmpy<<1],mn[(tmpy<<1)+1]),tmpy>>=1;
		}
		else
		{
			int tmpx=query_min(1,1,n,x,y),tmpy=query_max(1,1,n,x,y);
			printf(tmpy-tmpx+1==y-x+1?"YES\n":"NO\n");
		}
	}
	return 0;
}
posted @ 2019-07-11 20:22  路人黑的纸巾  阅读(158)  评论(0编辑  收藏  举报