#4046. 矮人排队(lineup)

题目描述

在七山七海之外的一个小村庄,白雪公主与 NNN 个矮人住在一起,所有时间都花在吃、和玩League of Legend游戏。白雪公主决心终结这样的生活,所以为他们举办了体育课。

在每节课开始的,矮人必须按他们的身高站队。假定矮人们有高度 1,2,⋯ ,N1,2,\cdots,N1,2,⋯,N(每个高度一次)。然而,由于不健康的生活方式,矮人的智力有所恶化,所以他们没有能力依照自己的高度排序。

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

1 X Y1XY1 X Y 在 XXX 和 YYY 位置的矮人必须互换位置。

她还通过发出以下形式的查询检查了他们的排序情况:

2 A B2AB2 A B 高度为 A,A+1,⋯ ,BA,A+1,\cdots,BA,A+1,⋯,B的矮人(不一定是按照这个顺序)是否已形成了当前队列的连续子序列?

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

输入的第一行包含两个正整数 NNN 和 MMM ,分别表示矮人的数量和白雪公主的命令数,2≤N≤200000,2≤M≤200000 2 \le N \le 200000, 2 \le M \le 200000 2≤N≤200000,2≤M≤200000

下面的行中包含 NNN 个用空格分离的从 111 到 NNN 的正整数,每个数只出现一次,代表矮人的初始排列。

接下来的 MMM 行包含白雪公主的一个单一的命令,如问题陈述中所描述的那样,形式为 1 X Y1XY1 X Y ,1≤X,Y≤N,X!=Y1 \le X,Y \le N,X!=Y1≤X,Y≤N,X!=Y ,或 2 A B2AB2 A B, 1≤A≤B≤N1 \le A \le B \le N 1≤A≤B≤N
输出格式

每行输出必须包含为每一个类型2查询的应答,“YES”或“NO”。
样例
样例输入

7 7
4 7 3 5 1 2 6
2 1 7
1 3 7
2 4 6
2 4 7
2 1 4
1 1 4
2 1 4

样例输出

YES
NO
YES
NO
YES

数据范围与提示

50%的数据 对于所有的类型2查询,B-A≤50恒成立
来源

coci2013 7th

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define N 200005
using namespace std;
int n,a[N],pos[N],m;
struct segment
{
	int l,r,mx_pos,mn_pos;
}t[N<<2];
void build(int p,int l,int r){
	t[p].l=l;t[p].r=r;
	if(l==r)return ;
	int mid=(l+r)>>1;
	build(p*2,l,mid);build(p*2+1,mid+1,r);
}
void change(int p,int pos,int val){
	if(t[p].l==t[p].r){
		t[p].mx_pos=val;
		t[p].mn_pos=val;
		return ;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(pos<=mid)change(p*2,pos,val);
	if(pos>mid)change(p*2+1,pos,val);
	t[p].mx_pos=max(t[p*2].mx_pos,t[p*2+1].mx_pos);
	t[p].mn_pos=min(t[p*2].mn_pos,t[p*2+1].mn_pos);
}
struct Ans
{
	int mx,mn;
};
Ans ask(int p,int l,int r){
	if(t[p].l>=l&&t[p].r<=r){
		return Ans{t[p].mx_pos,t[p].mn_pos};
	}
	int mid=(t[p].l+t[p].r)>>1;
	Ans ans;ans.mx=0;ans.mn=200005+100;Ans son_ans;
	if(l<=mid){son_ans=ask(p*2,l,r);ans.mx=max(ans.mx,son_ans.mx);ans.mn=min(ans.mn,son_ans.mn);}
	if(r>mid){son_ans=ask(p*2+1,l,r);ans.mx=max(ans.mx,son_ans.mx);ans.mn=min(ans.mn,son_ans.mn);}
	return ans;
}
	
int main()
{
	
	scanf("%d%d",&n,&m);
	build(1,1,n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		change(1,a[i],i);
	}
	for(int i=1;i<=m;++i){
		int op,x,y;scanf("%d%d%d",&op,&x,&y);
		if(op==1){
			int x_num=a[x],y_num=a[y];
			change(1,x_num,y);change(1,y_num,x);
			a[x]=y_num;a[y]=x_num;
		}else{
			if(x>y)swap(x,y);
			Ans ans=ask(1,x,y);
			if(ans.mx-ans.mn>y-x)printf("NO\n");
			else printf("YES\n");
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值