题: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 ",ans[i]); } return 0; }