链接:登录—专业IT笔试面试备考平台_牛客网https://ac.nowcoder.com/acm/contest/34442/G
来源:牛客网
题目描述
Rolnan有一个长度为 nnn 的数组 AAA,他给出了 mmm 个询问,每个询问包含三个整数 l,r,kl,r,kl,r,k ,他的目标是将子序列 Al,Al+1,…,ArA_l,A_{l+1},\dots,A_rAl,Al+1,…,Ar 归零。
Rolnan可以施展魔法,每次能够选择一个数字\textbf{一个数字}一个数字进行以下一种操作:
1、Ai→(Ai+1) mod k1、A_i\to (A_i+1)\ mod\ k1、Ai→(Ai+1) mod k
2、Ai→(Ai−1) mod k2、A_i\to (A_i-1)\ mod\ k2、Ai→(Ai−1) mod k
请问对于子序列 Al,Al+1,…,ArA_l,A_{l+1},\dots,A_rAl,Al+1,…,Ar 最少需要施展多少次魔法。
输入描述:
第一行两个整数 n,mn,mn,m 表示数组长度和询问次数。 接下来一行 nnn 个整数表示数组 AAA。 接下来 mmm 行,每行三个整数 l,r,kl,r,kl,r,k,询问最少施展多少魔法能够将子序列 Al,Al+1,…,ArA_l,A_{l+1},\dots,A_rAl,Al+1,…,Ar 全都变为 000 。
输出描述:
对于每个询问,输出一个整数,表示答案。
示例1
输入
复制6 3 1 1 4 5 1 4 3 5 10 1 4 11 1 4 6
6 3 1 1 4 5 1 4 3 5 10 1 4 11 1 4 6
输出
复制10 11 5
10 11 5
备注:
1≤n≤2×105,k≤109,1≤l≤r≤n,m≤2×105,∀i∀k{Ai∈[0,k)}1\le n\le 2\times 10^5,k\le 10^{9},1\leq l \leq r \leq n, m\leq 2\times 10^5, \forall i \forall k\{A_i\in [0,k)\}1≤n≤2×105,k≤109,1≤l≤r≤n,m≤2×105,∀i∀k{Ai∈[0,k)} 每组询问是单独的,不会改变数组 AAA 。 可以发现,对于每一组数(l,r,k),只需要分两步计算答案即可,对于a[i]<=k/2的值,显然是将其减到0划 算,对答案的贡献就是a[i];对于a[i]>k/2的值,显然是将其加到k划算,对答案的贡献为k-a[i]。 因此最简单的方案的复杂度为 O(N*N)。 现在考虑优化,本质上我们只需要找出区间(l,r) 内,大于k/2的数的数量,并且计算数据和,
其实后面有一个更简单的方法,就是先找出整个数组里面的最小值,要是k大于等于两倍最小值的话,就是等于l到r的前缀和,要是不是的话就是a[i]与k-a[i]的最小值,再浅浅求个和,就可以
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N];
ll n,m;
ll ans;
ll s[N];
int main(){
int i,j;
cin>>n>>m;
ll ed=-1;
for(i=1;i<=n;i++)
{
cin>>a[i];
ed=max(a[i],ed);
s[i]=s[i-1]+a[i];
}
while(m--)
{
int l,r,k;
cin>>l>>r>>k;
ans=0;
if(k>=2*ed) cout<<s[r]-s[l-1]<<endl;
else
{
for(i=l;i<=r;i++) ans+=min(a[i],k-a[i]);
cout<<ans<<endl;
}
}
return 0;
}