Manipulate Dwarfs
分类:线段树
1.题意概述
- 给你一个高度为1…n的数列,开始位置从1…n排好,你有两个操作:
- 1 X Y ——表示交换数列中高度为x和y的位置
- 2 A B ——询问连续的高度为 A、A+1、...、B 是否在这个序列中处于连续的一段位置?(不一定要按照递增顺序)
2.解题思路
- 先考虑
h[1...n]
数组维护每个高度所在下标,线段树维护
h
数组内的区间(连续高度)的下标最值。那么对于操作1,直接
swap(h[x],h[y]) 即可,而操作2,我们直接查询 h[A] ~ h[B] 区间的最大值(即最右侧是下标)与区间的最小值(即最左侧下标)的宽度是否等于 B−A 即可!
3.AC代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 200100
#define lson root << 1
#define rson root << 1 | 1
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct tree
{
int l, r, maxw, minw;
} t[maxn * 4];
int h[maxn];
void pushup(int root)
{
t[root].maxw = max(t[lson].maxw, t[rson].maxw);
t[root].minw = min(t[lson].minw, t[rson].minw);
}
void build(int l, int r, int root)
{
t[root].l = l;
t[root].r = r;
if (l == r)
{
t[root].maxw = t[root].minw = h[l];
return;
}
int mid = l + r >> 1;
build(l, mid, lson);
build(mid + 1, r, rson);
pushup(root);
}
void update(int pos, int l, int r, int root)
{
if (l == r && l == pos)
{
t[root].maxw = t[root].minw = h[l];
return;
}
int mid = l + r >> 1;
if (pos <= mid)
update(pos, l, mid, lson);
else
update(pos, mid + 1, r, rson);
pushup(root);
}
void query(int & a, int & b, int x, int y, int l, int r, int root)
{
if (x <= l && r <= y)
{
a = min(a, t[root].minw);
b = max(b, t[root].maxw);
return;
}
int mid = l + r >> 1;
if (x <= mid)
query(a, b, x, y, l, mid, lson);
if (y > mid)
query(a, b, x, y, mid + 1, r, rson);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
int n, m;
while (~scanf("%d%d", &n, &m))
{
for (int i = 1; i <= n; i++)
h[i] = i;
build(1, n, 1);
while (m--)
{
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if (op == 1)
{
swap(h[x], h[y]);
update(x, 1, n, 1);
update(y, 1, n, 1);
}
else
{
int a = n + 1, b = 0;
query(a, b, x, y, 1, n, 1);
if (b - a == y - x)
puts("YES");
else
puts("NO");
}
}
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time = %ld ms.", _end_time - _begin_time);
#endif
return 0;
}