正睿20NOIp前冲刺day10
估分:0+50+0+20=70
实际:20+40+20+20=100
T1:
写的是贪心,过了两个比较水的点
把数组从k往左往右看成两个序列,再求前缀和,得a和b,问题变成,开始i=j=1,要求每刻a[i]+b[j]<=0,每次可以i+1或j+1,问能否把i,j都移动到末尾。我们每次分别找到一个i,j之后的最小的数,然后把i或j移动到那里,这样最后i,j都停在序列中最小的位置,再逆序从序列末尾走到最小值这,走得到就是Yes,否则就是No
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 const int N = 100010; 10 11 int n, m, k; 12 LL a[N], sl[N], sr[N]; 13 14 int main() 15 { 16 int T; 17 scanf("%d", &T); 18 while (T--) 19 { 20 scanf("%d%d", &n, &k); 21 for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); 22 23 memset(sr, 0, sizeof(sr)); 24 memset(sl, 0, sizeof(sl)); 25 for (int i = k + 1, j = 1; i <= n; i++, j++) sr[j] = sr[j - 1] + a[i]; 26 for (int i = k, j = 1; i > 1; i--, j++) sl[j] = sl[j - 1] + a[i]; 27 m = n - k, n = k - 1; 28 29 int l = 0, r = 0, l1 = n, r1 = m; 30 bool ans = false; 31 while (true) 32 { 33 bool flag1 = true, flag2 = true; 34 for (int i = l; i <= n && sl[i] + sr[r] <= 0; i++) 35 { 36 if (sl[i] <= sl[l] && i != l) l = i, flag1 = false; 37 } 38 for (int i = r; i <= m && sr[i] + sl[l] <= 0; i++) 39 { 40 if (sr[i] <= sr[r] && i != r) r = i, flag2 = false; 41 } 42 if (l == n && r == m) { puts("Yes"); ans = true; break; } 43 if (flag1 && flag2) break; 44 } 45 if (ans) continue; 46 47 while (true) 48 { 49 bool flag1 = true, flag2 = true; 50 for (int i = l1; i >= l && sl[i] + sr[r1] <= 0; i--) 51 { 52 if (sl[i] <= sl[l1] && i != l1) l1 = i, flag1 = false; 53 } 54 for (int i = r1; i >= r && sl[l1] + sr[i] <= 0; i--) 55 { 56 if (sr[i] <= sr[r1] && i != r1) r1 = i, flag2 = false; 57 } 58 if (l1 == l && r1 == r) { puts("Yes"); ans = true; break; } 59 if (flag1 && flag2) break; 60 } 61 if (!ans) puts("No"); 62 } 63 }
T2:
忘记最后的判断了,少了10pts
没写完
T3:
如果是极限数据的话过不了的,然而不是
没看
T4:
20分纯暴力
没看
总结:
感觉确实难,还是失误了10分,检查代码还得仔细点