题面:输出长度为N的数列中区间和绝对值最小的绝对值,若有多个最小区间和绝对值,则输出其可能的最长长度。N<=10^5
思路:把区间转换成前缀和,区间绝对值最小其实就是前缀和之差的绝对值最小,所以我们将其排序即可,相差最小的区间一定出现在排序后相邻的两个前缀和之中。
但是还要注意一些问题:
①若有多个区间的值相同,则应将他们再按端点排序,然后选择端点相差最大的两个。
②循环边界和更新条件需要仔细揣摩。
但是吧。。虽然上面两条我都没有考虑到,但还是A了这道题。。所有正确的点,9个点。。
至于还有一个点。。这个题的数据应该是有问题,我把数据下下来暴力做了一遍,也跟“正确答案”不一样。
代码:
#include<iostream>
思路:把区间转换成前缀和,区间绝对值最小其实就是前缀和之差的绝对值最小,所以我们将其排序即可,相差最小的区间一定出现在排序后相邻的两个前缀和之中。
但是还要注意一些问题:
①若有多个区间的值相同,则应将他们再按端点排序,然后选择端点相差最大的两个。
②循环边界和更新条件需要仔细揣摩。
但是吧。。虽然上面两条我都没有考虑到,但还是A了这道题。。所有正确的点,9个点。。
至于还有一个点。。这个题的数据应该是有问题,我把数据下下来暴力做了一遍,也跟“正确答案”不一样。
代码:
#include<iostream>
using namespace std;
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
typedef long long lld;
lld a[100001];
struct S{
lld s;
int i;
bool operator < (S a) const{
if(s!=a.s)return s<a.s;
else return i<a.i;
}
}s[100002];
int main(){
int ansl,tmpl,i,N,j;
lld anss=0x7fffffffffffffffLL,tmps;
scanf("%d",&N);
s[0]=(S){0,0};
for(i=1,++N;i<N;++i){
scanf("%I64d",a+i);
s[i].s=s[i-1].s+a[i];
s[i].i=i;
}
sort(s,s+N);
s[N].s=1LL<<62;
for(i=0,--N;i<N;++i){
if(s[i].s==s[i+1].s){
if(anss){
anss=0;
ansl=0;
}
j=i;
while(s[i].s==s[i+1].s)++i;
ansl=max(abs(s[i].i-s[j].i),ansl);
}
tmps=abs(s[i].s-s[i+1].s);
tmpl=abs(s[i].i-s[i+1].i);
if(tmps<anss||tmps==anss&&tmpl>ansl){
anss=tmps;
ansl=tmpl;
}
}
cout<<anss<<endl<<ansl;
}