第十九届同济大学程序设计竞赛 G-归零(前缀和版)

输入:

6 3
1 1 4 5 1 4
3 5 10
1 4 11
1 4 6

输出:

10
11
5

AC代码:(前缀和优化版本) 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l,r,k,t,i,mx,ans,sum[200005];
int a[200005];
int main(){
    scanf("%lld %lld",&n,&t);
    for(i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i] = sum[i-1] + a[i];//数组A的前缀和 
        if (mx < a[i])//求Ai的最大值 
            mx = a[i];
    }
    while(t--){
        scanf("%lld%lld%lld",&l,&r,&k);
        if (mx * 2 <= k)//当数组A中的数都比较小时,此时全部进行操作2,使用前缀和,复杂度为2*10^5 
            ans = sum[r] - sum[l-1];
        else//当数组中的数有比较大的时候,此时只能一个个数去算,复杂度为 2*10^5*2*10^5=4*10^10 
		{//虽然 4*10^10肯定会超时,但测试样例有很多都是数比较小的,不会进行到这一步,所以可以凑巧AC 
            ans = 0;
            for(i = l; i <= r; i++)
			{
                if(a[i]<= k -a[i])
                    ans += a[i];
                else
                    ans += (k - a[i]);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

如果该题的数据没有那么仁慈的话,那么简单的前缀和优化也AC不了了,最保底的做法应该是用主席树(前缀和+权值线段树)不过我现在还不会呜呜...

猜你喜欢

转载自blog.csdn.net/weixin_61725823/article/details/124960075