题意:给你一个环形数组,让你求将这个数组分成 每段和 <= k 的最小段数。
解题思路:滑窗求的以 i结尾的 最长段长度,然后枚举最小的那个段长度中的值为终点搜索(因为必定有一个分割点在 最小段长上)
解题代码:
1 // File Name: e.cpp 2 // Author: darkdream 3 // Created Time: 2015年04月05日 星期日 14时55分31秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #include<stack> 11 #include<bitset> 12 #include<algorithm> 13 #include<functional> 14 #include<numeric> 15 #include<utility> 16 #include<sstream> 17 #include<iostream> 18 #include<iomanip> 19 #include<cstdio> 20 #include<cmath> 21 #include<cstdlib> 22 #include<cstring> 23 #include<ctime> 24 #define LL long long 25 #define maxn 3000005 26 using namespace std; 27 int n , q; 28 int a[maxn]; 29 int from[maxn]; 30 int tans ; 31 int pp; 32 int read_int() { 33 char ch = getchar(); 34 while (!isdigit(ch)) { 35 ch = getchar(); 36 } 37 int ret = 0; 38 while (isdigit(ch)) { 39 ret = ret * 10 + ch - '0'; 40 ch = getchar(); 41 } 42 return ret; 43 } 44 int main(){ 45 // freopen("input","r",stdin); 46 scanf("%d %d",&n,&q); 47 for(int i = 1;i <= n;i ++) 48 { 49 a[i] = read_int(); 50 a[i+n] = a[i]; 51 } 52 while(q--) 53 { 54 LL lim; 55 cin >>lim; 56 LL tsum =0 ; 57 int ans = 1e9 ; 58 int milr = 1e9 ; 59 int l ,r ; 60 l = 2*n; 61 r = 2*n-1; 62 int j = 1; 63 for(int i = 1;i <= 2* n ;++i) 64 { 65 tsum += a[i]; 66 while(tsum > lim ) 67 { 68 tsum -= a[j]; 69 j ++; 70 } 71 from[i] = j-1; 72 if(i - (j-1)< milr && i >= n) 73 { 74 l = j-1; 75 r = i ; 76 milr = (i-(j-1)); 77 } 78 } 79 for(int i = n+1;i <= 2* n;i ++) 80 from[i+n] = from[i]+n; 81 if(l < n) 82 { 83 l += n ; 84 r += n ; 85 } 86 //printf("%d %d ",l,r); 87 for(pp = l;pp <= r;pp++) 88 { 89 tans = 0 ; 90 for(int i = pp ;i >= 0;i = from[i]) 91 { 92 tans ++ ; 93 if(i <= pp -n) 94 { 95 break; 96 } 97 } 98 ans = min(ans,tans-1); 99 } 100 printf("%d ",ans); 101 102 } 103 104 105 return 0; 106 }