题意:给出一个数列,如果它的前i(1<=i<=n)项和都是正的,那么这个数列是正的,问这个数列的这n种变换里,
A(0): a1,a2,…,an-1,an
A(1): a2,a3,…,an,a1
…
A(n-2): an-1,an,…,an-3,an-2
A(n-1): an,a1,…,an-2,an-1
有多少是正的数列。
思路:比赛的时候想了很久很久,肯定是要求在一次线性扫描里solve这个两重循环才能解决的问题,最后想到应该是计算负数会影响的项,然后大腿就想出来了。
很巧妙地线性扫描,每次只要向前遍历,看这个负数会影响到哪一项,继续向前找就可以了,有些负数可以跳过的,于是就是一次循环解决了,模拟一下过程就知道了。注意最后,要扫描到temp>0或者直接扫描到i=0就可以了。【ACMer的脑洞可怕....】
#include <stdio.h> #include <string.h> #include <iostream> #define maxn 500010 using namespace std; double a[maxn]; int cas = 0; int main() { int t; scanf("%d", &t); while(t--) { int n; scanf("%d", &n); for (int i=0; i<n; ++i) { scanf("%lf", &a[i]); } double temp = 0; bool vis[maxn]; memset(vis, 0, sizeof(vis)); bool flag = true; int sum = n; for (int i=n-1; i>=0; --i) { if (a[i]<=0 && flag) flag = false; if (flag == false) { temp += a[i]; if (temp <= 0) vis[i] = 1, sum--; else flag = true, temp = 0; } } if (temp <= 0) { for (int i=n-1; i>=0; --i) { temp += a[i]; if (temp <= 0 && !vis[i]) { vis[i] = 1; sum--; } else if (temp > 0) break; } } printf("Case %d: %d\n", ++cas, sum); } return 0; }