zoukankan      html  css  js  c++  java
  • Time to Raid Cowavans ( 非分块sqrt(n)算法 + 离线查询特性应用

    题意:给定数组c[n],及多组a,b ,求每一组的后缀和 c[a]+c[a+b]+c[a+2*b]+c[a+3*b].......

    分析:

     对于每一个b值 ,都可以在o(n)的复杂度内利用dp 求出该b下不同a值对应的后缀和sum[a]:

                     for( int j=n ;j>=1 ;j--){
                         if( j > n-q[i].b )sum[j] = a[j] ;
                         else sum[j] = sum[ j+q[i].b ] + a[j];
                     }

    dp一次后,对于不同a值的询问都是o(1)复杂度的;

    我们也可以暴力在o(n/b)的复杂度内对一组a,b求解:

                 while( q[i].a <=n){
                     ans[ q[i].id ]+=a[ q[i].a ];
                     q[i].a+=q[i].b;
                 }

    以sqrt(n)分界,b大于sqrt(n)暴力复杂度为o(sqrt(n)),可以接受;

    b小于sqrt(n)直接dp,最多有sqrt(n)个不同b值,复杂度为o( n*sqrt(n) ),可以接受;

    由于没有在线查询,即输入一组数据立即给出答案,我们可以对每一组(a,b)按b排序,b相同的一起处理,相同的b只用一次dp就够了,然后把每一次的结果存在ans[i]中,按查询顺序输出即可

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int sq , n ,m;
    
    ll  a[300000+500];
    ll  ans[300000+500] ,sum[300000+500];
    
    struct Query{
         int id, a ,b;
    } q[300000+500];
    
    bool cmp( const Query & a ,const Query & b){
          return a.b < b.b;
    }
    int main( ){
         scanf("%d" ,&n);
         sq = sqrt( n );
         for( int i=1 ;i<=n ;i++)
            scanf( "%I64d" ,&a[i]);
         scanf("%d" ,&m);
         for( int i=1 ;i<=m ;i++){
             q[i].id = i;
             scanf( "%d%d" ,&q[i].a ,&q[i].b);
         }
    
         q[0] . b=0;
    
         sort( q+1 ,q+1+m ,cmp);
         for( int i=1 ;i<=m ;i++){
             if( q[i] .b <sq){
                 if( q[i].b != q[i-1].b){
                     for( int j=n ;j>=1 ;j--){
                         if( j > n-q[i].b )sum[j] = a[j] ;
                         else sum[j] = sum[ j+q[i].b ] + a[j];
                     }
                 }
                 ans[ q[i].id ]=sum[ q[i].a ];
             }
             else {
                 ans[ q[i].id ] = 0;
                 while( q[i].a <=n){
                     ans[ q[i].id ]+=a[ q[i].a ];
                     q[i].a+=q[i].b;
                 }
             }
         }
    
         for( int i=1 ;i<=m ;i++)
            printf("%I64d
    " ,ans[i]);
         return 0;
    }
  • 相关阅读:
    npm常用命令
    关于事件委托和时间冒泡(以及apply和call的事项)
    js 杂记
    angular中关于ng-repeat的性能问题
    关于日期的一些东西
    杂记
    angular中关于自定义指令——repeat渲染完成后执行动作
    angular中事件戳转日期的格式
    ES6-promise
    angular中ng-class的一些用法
  • 原文地址:https://www.cnblogs.com/-ifrush/p/10740244.html
Copyright © 2011-2022 走看看