zoukankan      html  css  js  c++  java
  • HDU Group

                                                          Group

    题目:

       给出n个数,是1-n的排列。要求你每次给你一个区间求出这个区间能够被分成的小区间个数。

    一个不连续的数能够被分成一个小区间。t-1,t或t,t+1表示连续。

    算法:

      高速做法应该是线段树。可是,我不会。

    学了一个块状数组。

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    const int MAXN = 100000 + 10;
    
    struct Node{
       int l,r,id,b;
    
       bool operator < (const Node& rhs) const {
           if(b != rhs.b){
              return b < rhs.b;
           }
           return r < rhs.r;
       }
    }query[MAXN];
    
    int seg[MAXN];
    bool vst[MAXN];
    int n,m,res;
    int ans[MAXN];
    
    void cal(int x,int &l,int &r){
        int L = query[x].l, R = query[x].r;
        while(L < l){  //须要将左右区间进行放大。否则可能出现左右游标交错的情况
            --l;
            int t = seg[l];
            vst[t] = 1;
            if(vst[t-1]&&vst[t+1]) --res;
            else if(!vst[t-1]&&!vst[t+1]) ++res;
        }
    
        while(R > r){
            ++r;
            int t = seg[r];
            vst[t] = 1;
            if(vst[t-1]&&vst[t+1]) --res;
            else if(!vst[t-1]&&!vst[t+1]) ++res;
        }
    
        while(L > l){
            int t = seg[l];
            vst[t] = 0;
            if(vst[t-1]&&vst[t+1]) ++res;
            else if(!vst[t-1]&&!vst[t+1]) --res;
           ++l;
        }
    
        while(R < r){
            int t = seg[r];
            vst[t] = 0;
            if(vst[t-1]&&vst[t+1]) ++res;
            else if(!vst[t-1]&&!vst[t+1]) --res;
            --r;
        }
    }
    
    void solve(){
       memset(vst,0,sizeof(vst));
       sort(query,query + m);
       res = 0;
       int l = query[0].l, r = query[0].r;
       for(int i = l;i <= r;++i){
           int t = seg[i];
           vst[t] = 1;
           if(vst[t-1] && vst[t+1]) --res;
           else if(!vst[t-1]&&!vst[t+1]) ++res;
       }
    
       ans[query[0].id] = res;
       for(int i = 1;i < m;++i){
           ans[query[i].id] = (cal(i,l,r),res);
       }
    
       for(int i = 0;i < m;++i){
          printf("%d
    ",ans[i]);
       }
    
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
    
            for(int i = 1;i <= n;++i){
                scanf("%d",&seg[i]);
            }
    
            int B = sqrt(1.0*n);
            for(int i = 0;i < m;++i){
                scanf("%d%d",&query[i].l,&query[i].r);
                query[i].b = query[i].l / B;
                query[i].id = i;
            }
    
            solve();
        }
        return 0;
    }


  • 相关阅读:
    【SPOJ】6779 Can you answer these queries VII
    【SPOJ】1557 Can you answer these queries II
    【SPOJ】2916 Can you answer these queries V
    【CodeForces】86D Powerful array
    【SPOJ】1043 Can you answer these queries I
    【HDU】3727 Jewel
    【HDU】3915 Game
    【SPOJ】1043 Can you answer these queries III
    【SPOJ】2713 Can you answer these queries IV
    成为一名更好的软件工程师的简单方法
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4591492.html
Copyright © 2011-2022 走看看