树状数组 线段树 again- -又不会处理 again- -
看了网上其他人的思路:
就是 要找出最少的分组 分组以数值连续为标准
还是以 右端点 为关键点
sum(i)为从 1~i(输入数下标)的最少分组个数
从左向右 不断的更新 r(i)
从第一个数开始扫描 当前数a[i]所对应的 i 向上update(i,1)加1
如果 在 i之前 1~i-1中的 数中有 a[i]+1 a[i]-1 则,这两个数 所在pos[a[i]+1], pos[a[i]-1】分别 向上update(pos,-1) 减1
(其实就是每扫描到一个新的数,在这个数上 加一个组,若之前有和它相邻的数,则和他相邻的数的位置要告诉自己和它的boss自己可以归在最新的那个组,自己和管理它的boss都要减少一组)
边更新边计算query的值 即 如果 i==query[].r (query的值 以 r的 非递减顺序存储)
query的时候 就 用 sum(r)-sum(l)
ok .其实还不是很理解
上code.
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAXN=100010;
int n,m,a[MAXN],c[MAXN],pos[MAXN],ans[MAXN];
struct node
{
int l,r,id;
}query[MAXN];
bool cmp(struct node a,struct node b)
{
return a.r<b.r;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int i,int val)
{
while(i<=n)
{
c[i]+=val;
i+=lowbit(i);
}
}
int sum(int a,int b)
{
int ar=0,br=0;
while(a)
{
ar+=c[a];
a-=lowbit(a);
}
while(b)
{
br+=c[b];
b-=lowbit(b);
}
return (br-ar);
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
int i,k=1;
for (i = 1; i <= n; i++) {
cin>>a[i];
pos[a[i]]=i;
}
for(i = 1;i <= m; i++){
cin>>query[i].l>>query[i].r;
query[i].id=i;
}
sort(query+1,query+1+m,cmp);
for (i = 1; i <= n; i++) {
update(a[i],1);
if(a[i]<n && pos[a[i]+1]<i)
update(pos[a[i]+1],-1);
if(a[i]>1 && pos[a[i]-1]<i)
update(pos[a[i]-1],-1);
while(k<=m && query[k].r==i)
{
ans[query[k].id]=sum(query[k].l,query[k].r);
k++;
}
}
for(i = 1; i <= m; ++i){
cout<<ans[i]<<endl;
}
}
return 0;
}