标签:upper font follow cstring 左右 target 分享图片 ase HERE
题意
给出一个整数列,求一段子序列之和最接近所给出的t。输出该段子序列之和及左右端点。
Input
Output
Sample Input
5 1
-10 -5 0 5 10
3
10 2
-9 8 -7 6 -5 4 -3 2 -1 0
5 11
15 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
15 100
0 0
Sample Output
5 4 4
5 2 8
9 1 1
15 1 15
15 1 15
分析
这道题可以看得出来是要用尺取法,尺取法的关键是要找到单调性。而序列时正时负,显然是不满足单调性的。
如果记录下前缀和,并排好序,这样就满足单调性了,就可以使用前缀和了
代码
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 #define RG register int 11 #define rep(i,a,b) for(RG i=a;i<=b;++i) 12 #define per(i,a,b) for(RG i=a;i>=b;--i) 13 #define ll long long 14 #define inf (1<<30) 15 #define maxn 100005 16 using namespace std; 17 int n,k; 18 int num[maxn]; 19 struct P{ 20 int id,s; 21 inline int operator < (const P &a)const{ 22 return s==a.s?id<a.id:s<a.s; 23 } 24 }p[maxn]; 25 inline int read() 26 { 27 int x=0,f=1;char c=getchar(); 28 while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 29 while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 30 return x*f; 31 } 32 33 void solve() 34 { 35 int aim=read(); 36 int l=0,r=1,mn=inf,al,ar,ans; 37 while(l<=n&&r<=n&&mn) 38 { 39 int cal=p[r].s-p[l].s; 40 if(abs(cal-aim)<mn) 41 { 42 mn=abs(cal-aim); 43 al=p[r].id,ar=p[l].id,ans=cal; 44 } 45 if(cal>aim) ++l; 46 else if(cal<aim) ++r; 47 else break; 48 if(l==r) ++r; 49 } 50 if(al>ar) swap(al,ar); 51 printf("%d %d %d\n",ans,al+1,ar); 52 } 53 54 int main() 55 { 56 while(1) 57 { 58 n=read(),k=read(); 59 if(!n&&!k) return 0; 60 rep(i,1,n) num[i]=read(); 61 p[0]=(P){0,0}; 62 rep(i,1,n) p[i].s=p[i-1].s+num[i],p[i].id=i; 63 sort(p,p+1+n); 64 rep(i,1,k) solve(); 65 } 66 return 0; 67 }
标签:upper font follow cstring 左右 target 分享图片 ase HERE
原文地址:https://www.cnblogs.com/ibilllee/p/9300321.html