题目链接: https://vjudge.net/problem/SPOJ-DWARFLOG
题意:
题意
N个小矮人的身高为1,2,…,N,初始按照身高从1到N的顺序排列,给出m次操作
.1 X Y 将身高为X和Y的小矮人交换位置
.2 A B 询问身高为A,A+1,…,B的小矮人是否位于连续的位置
数据
第一行为N和M,2 <= N <= 200000,2 <= M <= 200000
接下来M行为“1 X Y”(1 <= X,Y <= N,X != Y)或者“2 A B”(1 <= A <= B)
输入
4 5
2 2 3
2 2 4
1 1 3
2 3 4
1 4 3
输出
YES
YES
NO
解题思路: 是bzoj 1067 的弱化版,不过判断连续都是一样方法,我们只要知道A到B的位置中最大的一个pd和最小的一个px,A到B连续当前仅当B-A=pd-px。所以我们直接用线段树维护就可以了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int n, m, a[maxn];
int mx[maxn<<2], mi[maxn<<2], L, R, P, m1, m2;
void build(int l, int r, int o){
if(l == r){
mx[o] = mi[o] = a[l];
}
else{
int mid = (l + r) / 2;
build(l, mid, o * 2);
build(mid + 1, r, o * 2 + 1);
mx[o] = max(mx[o * 2], mx[o * 2 + 1]);
mi[o] = min(mi[o * 2], mi[o * 2 + 1]);
}
}
void update(int l, int r , int o){
if(l == r && l == P){
mx[o] = mi[o] = a[l];
}
else{
int mid = (l + r) / 2;
if(P <= mid) update(l, mid, o * 2);
else update(mid + 1, r, o * 2 + 1);
mx[o] = max(mx[o * 2], mx[o * 2 + 1]);
mi[o] = min(mi[o * 2], mi[o * 2 + 1]);
}
}
void query(int l, int r, int o){
if(L <= l && r <= R){
m1 = max(m1, mx[o]);
m2 = min(m2, mi[o]);
}
else{
int mid = (l + r) / 2;
if(L <= mid) query(l, mid, o * 2);
if(mid < R) query(mid + 1, r, o * 2 + 1);
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) a[i] = i;
build(1, n, 1);
while(m--){
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if(op == 1){//update
swap(a[x], a[y]);
P = x; update(1, n, 1);
P = y; update(1, n, 1);
}
else{ //query
m1 = 0; m2 = n + 1;
L = x, R = y;
query(1, n, 1);
//cout << m1 << " " << m2 << endl;
if(m1 - m2 == R - L){
puts("YES");
}
else{
puts("NO");
}
}
}
return 0;
}