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]);
}
}