题意:有n个小孩,他们手上有很多糖果,善良的小孩会告诉你他有多少糖果,相反,则不会告诉你,但是会告诉你他和他的邻居的糖果和,求出每个人最多拥有多少糖果。
题目链接:http://acm.zju.edu.cn/changsha/showProblem.do?problemId=31
思路:n个人的号码是有1-n,,由于每次给出的是三个数的和(最边上的可以认为是0),很容易确定3,6,9,12,,,,,,的糖果数量,
另外,在以下几种情况下,这个序列的值都可以确定:
1.如果在剩余的那些号码中有已知的量,那么这个序列的值都可以确定;
2.如果n%3==0 || n%3==1 这个序列分别从头到尾和从尾到开始在求一次就可以确定;
那么接下来的情况(n%3==2)就是不确定这个序列,(除了Mode3==0的位置确定外)
对于以下序列 a,b,c,d,e,f,g,h,,,,,,
sum1=a+b; sum2=a+b+c; sum3=b+c+d; sum4=c+d+e;
sum5=d+e+f; sum6=e+f+g; sum7=f+g+h; sum8=g+h;
由于确定c,f,的值,那么上述不等式可以转换为:
x1 = a + b; x2 = b + d; x3 = d + e; x4 = e + g; x5 = g + h; (x1,x2,x3,x4,x5都可以求出来)
那么上述的这些式子就全部可以转换为和a有关系的函数式: b = x1 - a ; d = x2 - b = x2 - x1 + a; ,,,,,,,,,,,,
每个变量本身是大于等于0,所以我们可以确定a的最大值和最小值,
从而每个变量的最大值也就确定~~~~~~~
比赛的时候没写出来,代码太渣,,,还是纪念下来,
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100010
#define inf 0x3f3f3f3f
int s[maxn]; //记录两个未知数的和
int num[maxn];
int num2[maxn];
int sum[maxn];
int main()
{
int n,m,query,pos;
while(~scanf("%d",&n)){
memset(s,0,sizeof(s));
memset(num,0,sizeof(num));
memset(num2,0,sizeof(num2));
memset(sum,0,sizeof(sum));
bool flag=false;
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
if(i%3){if(num[i]!=-1) {flag=true;pos=i;}} //记录是否有除了3,6,9..之外的值给出。。。
num2[i]=num[i];
}
for(int i=1;i<=n;i++)
scanf("%d",&sum[i]);
for(int i=1;i<=n;i++) //确定位置3.6.9.12....的值
if(i%3==0) num[i] = sum[i-1] - sum[i-2] + num[i-3];
if(n%3==0){ //确定n%3==0序列
for(int i=n;i>=1;i--) //确定mode3==1的位置的数
if(i%3==1)
num[i] = sum[i+1] - sum[i+2] + num[i+3];
for(int i=1;i<=n;i++)
if(i%3==2) //确定mode3==2的位置的数
num[i] = sum[i] -num[i-1] -num[i+1];
scanf("%d",&m);
while(m--){
scanf("%d",&query); query++;
printf("%d\n",num[query]);
}
}
else if(n%3==1){ //确定n%3==1序列
num[n] = sum[n] - num[n-1];
for(int i=n-2;i>=1;i--)
num[i] = sum[i+1] - num[i+1] -num[i+2];
scanf("%d",&m);
while(m--){
scanf("%d",&query); query++;
printf("%d\n",num[query]);
}
}
else{
if(flag==true){ //有值给出的情况
if(pos%3==2){
num[pos-1] = sum[pos-1] -num[pos-2] -num[pos];
pos=pos-1;
}
for(int i=pos-2;i>=1;i--)
num[i]=sum[i+1]-num[i+1] -num[i+2];
for(int i=pos+1;i<=n;i++)
num[i]=sum[i-1]-num[i-1]-num[i-2];
scanf("%d",&m);
while(m--){
scanf("%d",&query);query++;
printf("%d\n",num[query]);
}
}
else{
int t=1; //记录两个变量的和
for(int i=1;i<=(n-2);i++){
if(i%3==2){
s[t++] = sum[i] - num[i+1];
s[t++] = sum[i+1] - num[i+1];
}
}
s[t] = sum[n];
int mi=0,ma=inf,temp=0,cnt=1; //记录a 的可变范围
for(int i=2;i<=n;i++){
if(i%3){
num[i] = s[cnt++] - temp;
if(i%3==1) mi=max(mi,-num[i]);
else if(i%3==2) ma=min(ma,num[i]);
temp=num[i];
}
}
num[1] = 0;
scanf("%d",&m);
while(m--){
scanf("%d",&query);
query++;
if(num2[query]!=-1) printf("%d\n",num2[query]);
else{
if(query%3==0) printf("%d\n",num[query]);
else if(query%3==1) printf("%d\n",num[query]+ma);
else printf("%d\n",num[query]-mi);
}
}
}
}
}
return 0;
}