您的位置:首页 > 其它

hdu 4638 Group (离线树状数组)

2015-08-01 21:22 316 查看
/*
题意:
在l到r之间有多少段连续的数

离线处理每个查询,遍历每个点,设当前处理的区间终点为R,
处理每个查询的时候,首先假设所有的数a[i]都是自己独立成段,
如果有a[i]+1,或者a[i]-1的数在区间[L,R]内,那么它肯定不是独立成段的,
也就是我们要减去在[L,R]内不独立成段的数的个数。
问题就转化为查询[L,R]之前不独立成段的数的个数。
可以这样处理,对于a[i],如果发现a[i]-1,或者a[i]+1的位置,
在[1,R]之间,那么我们在相应位置加上1,直接查询区间[L,R]内有多少1就可以了。
*/
# include <stdio.h>
# include <algorithm>
# include <string.h>
using namespace std;
struct node
{
int l,r,poss;
};
node p[100010];
int c[100010];
int n;
bool cmp(node a1,node a2)
{
if(a1.r==a2.r)
return a1.l<a2.l;
return a1.r<a2.r;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int p,int val)
{
while(p<=n)
{
c[p]+=val;
p+=lowbit(p);
}
}
int sum(int x)
{
int res=0;
while(x>0)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
int a[100010];
int pos[100010];
int num[100010];
int main()
{
int t,m,i,j;
while(~scanf("%d",&t))
{
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++)
{
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(i=1; i<=m; i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].poss=i;
}
sort(p+1,p+1+m,cmp);
memset(c,0,sizeof(c));
j=1;
for(i=1; i<=n; i++)
{
update(i,1);
if(pos[a[i]+1]<i&&a[i]<n)
update(pos[a[i]+1],-1);
if(pos[a[i]-1]<i&&a[i]>1)
update(pos[a[i]-1],-1);
while(j<=m&&p[j].r==i)
{
num[p[j].poss]=sum(p[j].r)-sum(p[j].l-1);
j++;
}
}
for(i=1; i<=m; i++)
printf("%d\n",num[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: