Group

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

题意:找到区间能,有多少组连续数字串 

题解:离线处理,从开始到1--n开始扫描,用树状数组记录每个位置构成组的情况。对于i位置上的数,一定会构成一个组,所以add(i,1),如果a[i]-1和a[i]+1在之前就已经出现,那么就可以删除了合并。add(pos[a[i]-1],-1),add(pos[a[i]+1],-1),如果有以i为右端点的查询,则该查询就是ans[id]=getsum(r)-getsum(l-1);

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 const int N=1e5+19;
 8 int c[N],a[N],ll[N],rr[N],ans[N],pos[N];
 9 bool flag[N];
10 int n,m;
11 vector<int>mp[N];
12 int lowbit(int x){
13   return x&(-x);
14 }
15 
16 void add(int x,int val){
17     while(x<=n){
18         c[x]+=val;
19         x+=lowbit(x);
20     }
21 }
22 int getsum(int x){
23     int sum=0;
24     while(x>0){
25         sum+=c[x];
26         x-=lowbit(x);
27     }
28    return sum;
29 }
30 int main(){
31    int T;
32    scanf("%d",&T);
33    while(T--){
34        scanf("%d%d",&n,&m);
35        for(int i=1;i<=n;i++){
36         scanf("%d",&a[i]);
37          pos[a[i]]=i;
38        }
39 
40        memset(c,0,sizeof(c));
41        memset(flag,0,sizeof(flag));
42         for(int i=1;i<=n;i++)
43            mp[i].clear();
44         for(int i=1;i<=m;i++){
45             scanf("%d%d",&ll[i],&rr[i]);
46             mp[rr[i]].push_back(i);
47         }
48         for(int i=1;i<=n;i++){
49             int pre=a[i]-1;
50             int next=a[i]+1;
51             if(pre>=1&&flag[pre]){
52                 add(pos[pre],-1);
53             }
54             if(next<=n&&flag[next]){
55                 add(pos[next],-1);
56             }
57              add(i,1);
58             flag[a[i]]=1;
59             int tt=mp[i].size();
60            for(int j=0;j<tt;j++){
61               int v=mp[i][j];
62               ans[v]=getsum(i)-getsum(ll[v]-1);
63            }
64         }
65          for(int i=1;i<=m;i++)
66            printf("%d\n",ans[i]);
67    }
68 
69 }
View Code

 

posted on 2014-10-02 15:50  天依蓝  阅读(378)  评论(0编辑  收藏  举报

导航