hdu4638 问一段区间能组成多少段连续的数

题:http://acm.hdu.edu.cn/showproblem.php?pid=4638

题意:题意为询问一段区间里的数能组成多少段连续的数。

分析:我们先从左到右地添加数,再假定添加进去的话那么连续段数就加1,由此我们加入一个数x后,要是x-1或x+1在这之前就已经加进去了,那么连续段数就要减一,要是x-1和x+1同时在之前已经加进去了那么就要减二;

   因为题目要求查询一段区间且没有强制在线,所以我们进行离线处理,每当处理完一段区间就记录答案即可;

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
int n;
int tr[M],pos[M],a[M],ans[M];
struct node{
    int l,r,id;
}q[M];
bool cmp(node x,node y){
    return x.r<y.r;
}
void update(int i,int c){
    while(i<=n)
        tr[i]+=c,i+=i&(-i);
}
int query(int i){
    int res=0;
    while(i)
        res+=tr[i],i-=i&(-i);
    return res; 
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int m;
        scanf("%d%d",&n,&m);
        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+1+m,cmp);
        int nowi=1;
        memset(tr,0,sizeof(tr));
        for(int i=1;i<=n;i++){
            update(i,1);
            if(a[i]>1&&pos[a[i]-1]<i)
                update(pos[a[i]-1],-1);
            if(a[i]<n&&pos[a[i]+1]<i)
                update(pos[a[i]+1],-1);
            while(nowi<=m&&q[nowi].r==i)
                ans[q[nowi].id]=query(q[nowi].r)-query(q[nowi].l-1),nowi++;
        }
        for(int i=1;i<=m;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
View Code

 

posted @ 2020-03-07 22:23  starve_to_death  阅读(180)  评论(0编辑  收藏  举报