题目描述
输入
输出
样例输入
样例输出
数据范围限制
提示
【样例解释】
样例一:L = 1, R = 3 样例二:L = 2, R = 5
样例一:L = 1, R = 3 样例二:L = 2, R = 5
题解:
这一题,是一道经典的前缀和问题。但是这里单单用前缀和就会N2超时。
所以呢,我们要换一种思路。
我们设fife的随从为A组,beny的随从为B组。sumxt表示T组的下标为X的战斗力(能力值的前缀和)。
所以原式就转换成求一下这个鬼东西的最小值:(设区间左边为L,右边为R)
abs(sumRA-sumLA-(sumRB-sumLB))(1<=L<=R<=n)
而上面那个鬼东西又等于下面这个鬼东西:
abs((sumRA-sumRB)-(sumLA-sumLB))(1<=L<=R<=n)———①
所以你就可以把sumRA-sumRB与sumLA-sumLB看成一种新的前缀和s,所以我们设:
si=sumiA-sumiB(1<=i<=n)
这样我们就把①式转化成了下面这个简洁的式子:
abs(sR-sL)
其实上面那个式子就是求两个s值的最小的差值。
对于这个,我们只要将s数组快排一遍,然后再枚举i,找出最小的si-si-1就够了。
为什么呢?因为当你排完了序之后,相邻的数总会在数轴上总会最靠近那个数(在同侧)。
所以相邻的数一定比不相邻的数(在同侧)的数更优。
所以我们就这样得出了答案。
看一看时间复杂度:
输入:O(N)
前缀和:O(N)
求s数组:O(N)
快排:O(N*log(N))
求最小值:O(N)
综上可得:我们的时间复杂度是O(N*log(N))。
万事俱备,只欠代码!
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long n,x,y,min1=0x3f3f3f3f,s1[300001],s2[300001],s[300001]; 4 //由于数据大小300000*1000000000肯定会爆int,所以要开long long! 5 int main() 6 { 7 scanf("%lld",&n); 8 for(int i=1;i<=n;i++) 9 { 10 scanf("%lld",&x); 11 s1[i]=s1[i-1]+x; 12 } 13 for(int i=1;i<=n;i++) 14 { 15 scanf("%lld",y); 16 s2[i]=s2[i-1]+y; 17 s[i]=s1[i]-s2[i]; 18 } 19 sort(s+1,s+n+1); 20 for(int i=1;i<=n;i++) 21 min1=min(min1,abs(s[i]-s[i-1])); 22 printf("%lld",min1); 23 return 0; 24 }
此题到此完结!