Group
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1723 Accepted Submission(s): 904
For each case first line is n, m(1<=n ,m<=100000) indicate there are n men and m query.
Then a line have n number indicate the ID of men from left to right.
Next m line each line has two number L,R(1<=L<=R<=n),mean we want to know the answer of [L,R].
题意:n个人,序号为1到n,将他们分尽可能少的组数,要求同组的人序号排序后是连续的。m次询问,求问询问的区间中的人至少可分成几组。
先将所有询问按右端点排序。将n个人依次存入线段树,当第i个人、序号为x的人加入线段树时,将其认为是独立的一组,则第i个结点的sum值加1,若序号为x - 1 或x + 1的人位置在他前面,则组数可以少1或2,则序号为x - 1 或x + 1的人所在位置所对应的结点sum值减1。
此时,若询问区间的右端点等于i,则答案为区间内所有结点的sum值之和。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ls node << 1
#define rs node << 1 | 1
#define lson l, mid, ls
#define rson mid + 1, r, rs
#define maxn 100005
using namespace std;
int n, m;
int sum[maxn << 2];
int a[maxn], p[maxn], ans[maxn];
struct B {
int l;
int r;
int id;
} b[maxn];
bool cmp(B x, B y)
{
return x.r < y.r;
}
void pushup(int l, int r, int node)
{
sum[node] = sum[ls] + sum[rs];
}
void build(int l, int r, int node)
{
if(l == r) {
sum[node] = 0;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
}
void update(int x, int v, int l, int r, int node)
{
if(l == x && r == x) {
sum[node] += v;
return;
}
int mid = (l + r) >> 1;
if(x <= mid)
update(x, v, lson);
else
update(x, v, rson);
pushup(l, r, node);
}
int query(int x, int y, int l, int r, int node)
{
if(l == x && r == y)
return sum[node];
int mid = (l + r) >> 1;
if(x > mid)
return query(x, y, rson);
else if(y <= mid)
return query(x, y, lson);
else
return query(x, mid, lson) + query(mid + 1, y, rson);
}
int main()
{
int t,cnt;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
build(1,n,1);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
p[a[i]] = i;
}
for(int i = 1; i <= m; i++) {
scanf("%d%d", &b[i].l, &b[i].r);
b[i].id = i;
}
sort(b + 1, b + m + 1, cmp);
cnt = 1;
for(int i = 1; i <= n; i++) {
update(i, 1, 1, n, 1);
//printf("*6*\n");
//cout << a[i] << " " << p[a[i] - 1] << endl;
if(a[i] > 1 && p[a[i] - 1] < i)
update(p[a[i] - 1], -1, 1, n, 1);
//cout << a[i] << " " << p[a[i] + 1] << endl;
if(a[i] < n && p[a[i] + 1] < i)
update(p[a[i] + 1], -1, 1, n, 1);
//printf("*5*\n");
while(cnt <= m && b[cnt].r == i) {
ans[b[cnt].id] = query(b[cnt].l, b[cnt].r, 1, n, 1);
cnt ++;
//printf("*3*\n");
}
}
//printf("*4*\n");
for(int i = 1; i <= m; i++)
printf("%d\n",ans[i]);
}
}