whu 1470 Join in tasks 计算推理

对于序列 a_1,a_2,..a_i.,a_n 从小到大排列处理花费会最小。

一个一个处理完,例如当处理 a_1

  则此时花费分为 a_1, 以及 a_x  (x>1)的花费来计算

    1. a_1 时   

    2. a_x 时  

  当消除掉 a_1 后,又生成一个新的 序列 a_1`, a_2`, ..., a_n`

  此时可以知道,  a_i` = a_i - a_1 + 1

  我们可以通过 线段树来 维护更新序列,这样省事. 但是这题 n = 1e5 , 且极限T = 100, 此时时间复杂度达到 1e7,

若再添加个 log(N) 复杂度,就会TLE了。

  我们可以发现总花费为  

  序列除了被减少外,未被覆盖之内。我们可以通过预处理前缀和来优化,达到 O(N).

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int mod = 1e9+7;
const int N = 1e5+10;
typedef unsigned long long LL; 
int a[N], n; 
LL s[N];

int main(){ 
    int T;
    scanf( "%d", &T );
    for( int Case = 1; Case <= T; Case++ ){
        scanf("%d", &n);  
        for(int i = 1; i <= n; i++) scanf("%d", &a[i] ); 
         sort( a+1, a+n+1 ); 
         s[0] = 0; a[0] = 1;
         for(int i = 1; i <= n; i++) s[i] = s[i-1]+a[i];
        LL res = 0;
        for(int i = 1; i <= n-1; i++){
            LL A = a[i]-a[i-1]+1 ;   //printf("A = %I64d\n", A);
            if( A > 0 ){ 
                if( A == 1 ) res = (res+(n-i))%mod;
                else { 
                    int tot = n-i;  
                    LL tmp_sum = (s[n]-s[i]) - 1LL*tot*(a[i-1]-1);  
                    LL tmp = (1LL*tot*A*(A+1)/2)%mod + (1LL*(tmp_sum-tot*(A-1))*(A-1)%mod+(1LL*tot*A*(A-1)/2)%mod )*tot%mod;   
                    res = (res+tmp+mod)%mod; 
                }
            }        
        }
        printf("Case %d: %I64d\n", Case, res );        
    }
    return 0;    
}

 

posted @ 2013-04-14 21:56  yefeng1627  阅读(258)  评论(3编辑  收藏  举报

Launch CodeCogs Equation Editor