2307. 选择

题目描述
 
输入
输出
 
样例输入
样例输出
 
数据范围限制
 
提示
【样例解释】
样例一: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 }

此题到此完结!

转载于:https://www.cnblogs.com/xinxiyuan/p/11341017.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值