hdu4638Group

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

求某一区间所包含的连续的段 对于乱序的数 到了i这个数所包含的段数 首先把这个数看作单独的段 再看一下前面是否出现了它的朋友 若出现了就说明前面已经加过这样单独的段了 就把前面的更新掉-1 这样始终保证一个段的最后一个值记录着这是第几个段 从左到右扫描一遍 离线处理后 这样用树状数组或者线段树进行区间求和就可以了

 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\n",ans[i]);
73     }
74     return 0;
75 }
View Code

 

posted @ 2013-08-02 12:28  _雨  阅读(230)  评论(0编辑  收藏  举报