http://acm.hdu.edu.cn/showproblem.php?pid=4638
求某一区间所包含的连续的段 对于乱序的数 到了i这个数所包含的段数 首先把这个数看作单独的段 再看一下前面是否出现了它的朋友 若出现了就说明前面已经加过这样单独的段了 就把前面的更新掉-1 这样始终保证一个段的最后一个值记录着这是第几个段 从左到右扫描一遍 离线处理后 这样用树状数组或者线段树进行区间求和就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #define N 100010 7 using namespace std; 8 #define lowbit(x) (x&(-x)) 9 int p[N],a[N],re[N],ans[N],n; 10 struct node 11 { 12 int l,r,id; 13 }q[N]; 14 bool cmp(node a,node b) 15 { 16 return a.r<b.r; 17 } 18 void add(int x,int da) 19 { 20 while(x<=n) 21 { 22 re[x]+=da; 23 x+=lowbit(x); 24 } 25 } 26 int getsum(int x) 27 { 28 int s=0; 29 while(x) 30 { 31 s+=re[x]; 32 x-=lowbit(x); 33 } 34 return s; 35 } 36 int main() 37 { 38 int i,j,m,t; 39 cin>>t; 40 while(t--) 41 { 42 scanf("%d%d",&n,&m); 43 memset(re,0,sizeof(re)); 44 for(i = 1; i <= n ; i++) 45 { 46 scanf("%d",&a[i]); 47 p[a[i]] = i; 48 } 49 for(i = 1; i <= m ;i++) 50 { 51 scanf("%d%d",&q[i].l,&q[i].r); 52 q[i].id = i; 53 } 54 sort(q+1,q+m+1,cmp); 55 j = 1; 56 for(i = 1 ; i <= n ;i++) 57 { 58 add(i,1); 59 if(a[i]<n&&p[a[i]+1]<i) 60 add(p[a[i]+1],-1); 61 if(a[i]>1&&p[a[i]-1]<i) 62 add(p[a[i]-1],-1); 63 while(j<=m&&q[j].r==i) 64 { 65 int x = getsum(q[j].r); 66 int y = getsum(q[j].l-1); 67 ans[q[j].id] =x - y; 68 j++; 69 } 70 } 71 for(i = 1; i <= m ; i++) 72 printf("%d ",ans[i]); 73 } 74 return 0; 75 }