zoj 3800

来源:互联网 发布:php高级程序员面试题 编辑:程序博客网 时间:2024/04/28 18:11


询问【l , r】 gcd 为c的组数


typedef  long  long  LL ;const    int  maxn = 100002 ;struct  SegTree{        int  add[maxn<<2] ;        LL   sum[maxn<<2] ;        void  make(int l , int r , int t){              add[t] = sum[t] = 0LL ;              if(l == r)  return  ;              int m = (l + r) >> 1 ;              make(l , m , t<<1) ;              make(m+1 , r , t<<1|1) ;        }        void  up(int t){              sum[t] = sum[t<<1] + sum[t<<1|1] ;        }        void  down(int t , int l , int r){              if(add[t]){                   int m = (l + r) >> 1 ;                   add[t<<1] += add[t] ;                   add[t<<1|1] += add[t] ;                   sum[t<<1] += (LL)add[t] * (m - l + 1) ;                   sum[t<<1|1] += (LL)add[t] * (r - m) ;                   add[t] = 0LL ;              }        }        void  update(int L , int R , int l , int r , int t){              if(L <= l && r <= R){                    add[t] += 1 ;                    sum[t] += r - l + 1 ;                    return  ;              }              down(t , l , r) ;              int m = (l + r) >> 1 ;              if(L <= m)  update(L , R , l , m , t<<1) ;              if(R > m)   update(L , R , m+1 , r , t<<1|1) ;              up(t) ;        }        LL    ask(int L , int R , int l , int r , int t){              if(L <= l && r <= R)  return sum[t] ;              down(t , l , r) ;              LL s = 0LL ;              int m = (l + r) >> 1 ;              if(L <= m) s += ask(L , R , l , m , t<<1) ;              if(R >  m) s += ask(L , R , m+1 , r , t<<1|1) ;              return  s ;        }}tree[52]  ;int   n  , m , q  ;int   gs[maxn] , to[58] ;int   a[maxn]  ;struct  state{        int l , c , id ;        state(){}        state(int l , int c , int id){             this->l = l ;             this->c = c ;             this->id = id ;        }};std::vector<state> ask[maxn] ;LL   ans[maxn]  ;std::pair<int , int> pt[maxn]  ;void  gao(){      int i  , j , t , c , l , r , all  , id , g ;      for(i = 0 ; i < m ; i++)  tree[i].make(1 , n , 1) ;      t = 0 ;      for(i = 1 ; i <= n ; i++){          for(j = 0 ; j < t ; j++){              c = std::__gcd(a[i] , pt[j].first) ;              pt[j].first = c ;          }          pt[t++] = std::make_pair(a[i] , 1) ;          c = 1 ;          for(j = 1 ; j < t ; j++){              if(pt[j].first == pt[c-1].first)  pt[c-1].second += pt[j].second ;              else   pt[c++] = pt[j] ;          }          t = c ;          all = 0 ;          for(j = 0 ; j < t ; j++){              id = gs[pt[j].first] ;              if(id != -1){                   l = all + 1 ;                   r = all + pt[j].second ;                   tree[id].update(l , r , 1 , n , 1) ;              }              all += pt[j].second ;          }          for(j = 0 ; j < ask[i].size() ; j++){               state s = ask[i][j] ;               ans[s.id] = tree[gs[s.c]].ask(s.l , i , 1 , n , 1) ;          }      }}int   main(){      int i , l , r  , c ;      while(cin>>n>>m>>q){           for(i = 1 ; i <= n ; i++)  scanf("%d" , &a[i]) ;           memset(gs , -1 , sizeof(gs)) ;           for(i = 0 ; i < m ; i++){                    scanf("%d" , &to[i]) ;                    gs[to[i]] = i ;           }           for(i = 1 ; i <= n ; i++)  ask[i].clear() ;           for(i = 0 ; i < q ; i++){                scanf("%d%d%d" ,&l , &r , &c) ;                l++ ;                ask[r].push_back(state(l , c , i)) ;           }           gao() ;           for(i = 0 ; i < q ; i++)  printf("%lld\n" , ans[i]) ;      }      return  0 ;}


0 0