输入:
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不了了,最保底的做法应该是用主席树(前缀和+权值线段树)不过我现在还不会呜呜...