题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4638
题意:给你一个n的排列,然后给你一个区间[L,R],问你区间中有多少个连续的段
思路:先预处理整个区间,当我们将第i个数加入序列时,会有3种结果:
1.a[i]-1和a[i]+1已经出现在a[i]之前了,添加a[i]进去等于合并了a[i]-1,a[i],a[i]+1,故有add(i, -1);
2.a[i]-1和a[i]+1只有一个在之前出现,则该数加进去不会影响后面的结果;
3.a[i]-1和a[i]+1全部在其后出现,则相当于添加a[i]这单独一段,故有add(i, 1);
这样我们执行sum(x)即可算出[1, x]内有多少段了,将m次询问离线处理,然后去动态的维护[i, r]这个区间的结果,即当处理a[i]前,sum(r)是[i, r]的结果,处理a[i]后,sum(r)是[i + 1, r]结果,处理方法也和上面类似,注意一下pos[0]和pos[n + 1]的值不能影响预处理和删除
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <utility>
#include <functional>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
const int maxn = 100010;
int n, m;
int bit[maxn], pos[maxn], ans[maxn], a[maxn];
struct node
{
int l, r, id;
bool operator < (const node &rhs) const
{
if (l != rhs.l) return l < rhs.l;
return r < rhs.r;
}
} q[maxn];
int lowbit(int x)
{
return x & (-x);
}
void add(int x, int v)
{
while (x <= n)
{
bit[x] += v;
x += lowbit(x);
}
}
int sum(int x)
{
int res = 0;
while (x)
{
res += bit[x];
x -= lowbit(x);
}
return res;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
memset(bit, 0, sizeof(bit));
scanf("%d%d", &n, &m);
pos[0] = pos[n + 1] = n + 1;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
pos[a[i]] = i;
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q + 1, q + m + 1);
for (int i = 1; i <= n; i++)
{
if (i > pos[a[i] - 1] && i > pos[a[i] + 1])
add(i, -1);
else if (i < pos[a[i] - 1] && i < pos[a[i] + 1])
add(i , 1);
}
// for (int i = 1; i <= n; i++)
// printf("%d ", bit[i]);
// printf("\n");
for (int i = 1, j = 1; i <= n && j <= m; i++)
{
while (q[j].l == i)
{
ans[q[j].id] = sum(q[j].r);
j++;
}
if (i > pos[a[i] - 1] && i > pos[a[i] + 1])
{
add(i, -1);
}
else if (i < pos[a[i] - 1] && i < pos[a[i] + 1])
{
add(i, -1);
add(pos[a[i] - 1], 1);
add(pos[a[i] + 1], 1);
}
else if (i < pos[a[i] - 1])
{
add(i, -1);
add(pos[a[i] - 1], 1);
}
else if (i < pos[a[i] + 1])
{
add(i, -1);
add(pos[a[i] + 1], 1);
}
}
for (int i = 1; i <= m; i++)
printf("%d\n", ans[i]);
}
return 0;
}