UVALive 7325 Book Borders
-------------------------------------------------------------------------------------------------------------
我们可以预处理除长度为L的区间能存下的从第一个单词开始的单词的次数
然后枚举区间长度从a到b 每次从一个区间最后一个单词结尾跳到另一个区间最后一个单词结尾
这样相邻两次跳跃的总长度至少为一个区间长度
设单词总长为$len$ 对于长度为$x$的区间 总的跳跃次数不超 $len\ /\ x * 2$
因此整个问题的复杂度根据调和级数分析发现是 $O(lenlog{len})$
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int N = 500010; 7 int a[N], pre[N], sum[N]; 8 char s[N]; 9 int len, n; 10 int main() 11 { 12 while(gets(s) != NULL) 13 { 14 n = 0; 15 len = strlen(s) + 1; 16 for(int i = 0; i < len; ++i) 17 { 18 if(s[i] < 'a' || s[i] > 'z') 19 { 20 ++n; 21 a[n] = i + 1 - sum[n - 1]; 22 sum[n] = sum[n - 1] + a[n]; 23 } 24 pre[i + 1] = n; 25 } 26 int L, R, ans, now; 27 scanf("%d%d", &L, &R); 28 getchar(); 29 ++L; 30 ++R; 31 for(int i = L; i <= R; ++i) 32 { 33 ans = -1; 34 now = 0; 35 while(now != len) 36 { 37 ans += a[pre[now] + 1]; 38 now = sum[pre[min(now + i, len)]]; 39 } 40 printf("%d\n", ans); 41 } 42 } 43 return 0; 44 }