题目链接:Click here~~
题意:
有 n 个人,每人手里有若干糖果,有一些人的糖果数量不确定,但给出每相邻三个人的糖果数量和(起始端和末尾端是两个人)。
然后给出若干询问,求出某个人的最大可能的糖果数量。
解题思路:
先将第二个条件中的 sum 相邻项作差,可以得出若干等式 a[3] - a[0] , a[4] - a[1] , a[5] - a[2] , …… , a[n-1] - a[n-4]。
然后在起始端和末尾端可以得到 a[2] 与 a[n-3] 的确定值,可以作为已知使用,再根据上面等式,可以推出所有与已知项下标差为 3的倍数 的项。
其实只要知道一个 a[i] 满足条件 2 % 3 != i % 3,就一定可以得出 a[0] 与 a[1] 里的其中一项,再根据等式 a[0] + a[1] 求出另一项,从而得出整个序列。
如果最后没有将序列确定,那么剩余的一定全部是 2 % 3 != i % 3 的项,且 2 % 3 = n % 3。
由于知道了序列中所有 2 % 3 == i % 3的项,那么可以将原来第二个条件中的 sum 减去已知的这些项,那么我们可以得到一个关于 相邻未知项的和 的等式组。
即 a[0] + a[1] , a[1] + a[3] , a[3] + a[4] ,a[4] + a[6] …… 然后引入两个 fact :
1、相邻项均为负相关,相隔一项均为正相关。
2、一旦某个项的值确定,所有项的值均确定。
于是不妨考虑 a[0] 取值的上界与下界,得出后,即可根据正负相关性,得到所求项的上界。
如何考虑这个上界与下界呢?
将所有的 a[i] 全部转化成 a[i] = (+/-) a[0] + c 的形式,根据 a[i] >= 0 这一唯一约束条件,得出关于 a[0] 的不等式组,求解即可。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 1e5 + 5; int a[N],b[N],sub[N],sum_add[N],sum_sub[N],n; void go_r(int pos) { if(pos+3 < n) { a[pos+3] = a[pos] + sub[pos]; go_r(pos+3); } } void go_l(int pos) { if(pos-3 >= 0) { a[pos-3] = a[pos] - sub[pos-3]; go_l(pos-3); } } int main() { //freopen("in.ads","r",stdin); int m; while(~scanf("%d",&n)) { int pos = -1; for(int i=0;i<n;i++) { scanf("%d",&a[i]); if(a[i] != -1 && i % 3 != 2) pos = i; } for(int i=0;i<n;i++) scanf("%d",&b[i]); for(int i=0;i+3<n;i++) sub[i] = b[i+2] - b[i+1]; a[2] = b[1] - b[0]; go_r(2); a[n-3] = b[n-2] - b[n-1]; go_l(n-3); if(pos != -1) { go_l(pos); go_r(pos); } if(a[1] != -1) { a[0] = b[0] - a[1]; go_r(0); } if(a[0] != -1) { a[1] = b[0] - a[0]; go_r(1); } int a0_min , a0_max; if(a[0] == -1) { a0_min = sum_add[0] = 0; for(int i=3;i<n;i+=3) { sum_add[i] = sum_add[i-3] + sub[i-3]; a0_min = max(a0_min,-sum_add[i]); } a0_max = sum_sub[1] = b[0]; for(int i=4;i<n;i+=3) { sum_sub[i] = sum_sub[i-3] + sub[i-3]; a0_max = min(a0_max,sum_sub[i]); } } scanf("%d",&m); while(m--) { int q; scanf("%d",&q); if(a[q] != -1) printf("%d\n",a[q]); else { if(q % 3 == 0) printf("%d\n",a0_max+sum_add[q]); else printf("%d\n",-a0_min+sum_sub[q]); } } } return 0; }