题目
Description
在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏。白雪公主决心终结这样的生活,所以为他们举办了体育课。 在每节课开始时,矮人必须按他们的身高站队。假定矮人们有高度1,2,…,N(每个人高度互不相同)。然而,由于不健康的生活方式,矮人的智力有所恶化,所以他们没有能力依照自己的高度排序。
因此,白雪公主发出以下形式命令帮助他们:
1 X Y:X和Y位置的矮人互换位置。
2 A B:询问高度为A,A+1,…, B的矮人(不一定是按照这个顺序)是否已形成了当前队列的连续子序列。
帮助矮人按照白雪公主的指示行动,并回答她的问题。
Input
输入的第一行包含两个正整数N和M,分别表示矮人的数量和白雪公主的命令数,2≤N≤200,000,2≤M≤200,000。
第二行包含N个用空格隔开的从1到N的正整数,每个数只出现一次,代表矮人的初始排列。
接下来的M行包含白雪公主的命令,形式为“1 X Y”(1≤X,Y≤N,X≠Y)或“2 A B”(1≤A≤B≤N)。
Output
对于每个命令2输出“YES”或“NO”。
解题思路
用两个线段树维护序列的最小值和最大值,显然 ( m a x − m i n ) = = ( y − x ) (max-min)==(y-x) (max−min)==(y−x)时有 Y E S YES YES。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200010;
struct SegmentTree{
int l,r,sum1,sum2;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum1(x) tree[x].sum1
#define sum2(x) tree[x].sum2
}tree[N*4];
int n,m,a[N],b[N];
void wh(int p){
sum1(p)=min(sum1(p*2),sum1(p*2+1));
sum2(p)=max(sum2(p*2),sum2(p*2+1));
}
void build(int p,int l,int r){
l(p)=l,r(p)=r;
if (l==r) {sum1(p)=sum2(p)=b[l]; return;}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
wh(p);
}
void change(int p,int k,int d){
if (l(p)==r(p)){
sum1(p)=sum2(p)=d;
return;
}
int mid=(l(p)+r(p))/2;
if (k<=mid) change(p*2,k,d);
if (k>mid) change(p*2+1,k,d);
wh(p);
}
int ask1(int p,int l,int r){
if (l<=l(p)&&r>=r(p)) return sum1(p);
int mid=(l(p)+r(p))/2;
if (r<=mid) return ask1(p*2,l,r); else
if (l>mid) return ask1(p*2+1,l,r); else
return min(ask1(p*2,l,mid),ask1(p*2+1,mid+1,r));
}
int ask2(int p,int l,int r){
if (l<=l(p)&&r>=r(p)) return sum2(p);
int mid=(l(p)+r(p))/2;
if (r<=mid) return ask2(p*2,l,r); else
if (l>mid) return ask2(p*2+1,l,r); else
return max(ask2(p*2,l,mid),ask2(p*2+1,mid+1,r));
}
int main()
{
// freopen("sa.txt","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[a[i]]=i;
build(1,1,n);
while (m--){
int x,y,z,g,gg;
scanf("%d%d%d",&z,&x,&y);
if (z==1) {
change(1,a[x],b[a[y]]); change(1,a[y],b[a[x]]);
g=b[a[y]]; b[a[y]]=b[a[x]]; b[a[x]]=g;
g=a[y]; a[y]=a[x]; a[x]=g;
} else {
g=ask1(1,x,y),gg=ask2(1,x,y);
if ((gg-g)==(y-x)) printf("YES\n"); else printf("NO\n");
}
}
}