题目链接: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;
}