题意:一个数列,给出这个数列中的某些位置的数,给出所有相邻的三个数字的和,数列头和尾处给出相邻两个数字的和。有若干次询问,每次问某一位置的数字的最大值。

分析:设数列为a1~an。首先通过相邻三个数字的和我们可以求出a3,a6,a9……是多少。a3=sum(a1,a2,a3)-sum(a1,a2)。a6=sum(a4,a5,a6)-sum(a3,a4,a5)。后面依次类推。

推到了数列的最右面,如果恰好知道了an或者a(n-1)中的一个,那么可以通过sum(an,a(n-1))减去它来求得另一个。

这个题还有个性质就是,只要知道数列中连续的两位就可以通过不断向两侧延伸的方法得到整个数列。因为任意相邻三个的和都知道,知道其中两个数自然可以得到第三个。

所以我们如果知道了最后两位则一定可以知道整个数列。同样如果根据已知的数列中的数和推出的数能得知两个已知的相邻的数的话,也可推出整个数列。

唯一一种无法确定该数列的情况就是我们,没有推出最后的两个数(即n%3==2的情况),且数列中已知给出的数也没有提供任何推出信息以外的信息。

这时我们就获得了一个不确定的数列,将数列中的数字ai按照i%3结果的不同分成三组,得0则已知。

得1的数之间互相是同增同减的,因为他们互相之间的差是一样的。a1-a4=sum(a1,a2,a3)-sum(a2,a3,a4)。得2的同理。所以这些同增同减的数字会同时取得最大值或最小值。

得1和得2的之间是此消彼涨的,因为他们互相之间的和是一样的。a1+a2=sum(a1,a2)    a2+a4=sum(a2,a3,a4)-a3    a4+a5=sum(a3,a4,a5)-a3 所以得1的取得最小值则得2的取得最大值,反之亦然。

在符合了这些和与差的条件之后,唯一会导致数列不合法的情况就是出现负数。我们只需要先对得1的随意娶个值,并推出整个数列后,根据最小数值调整所有得1的取值,使最小的那个数恰好为0。

这样就可以使得1的取最小值,即让得2的取得最大值。

同理可以求得得1的最大值。

存储好各种最大值之后按题目中的询问输出即可。计算最大值需要O(n),每次询问需要O(1),共m次询问,总复杂度为O(n + m)。

#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std; #define MAX_NUM 100005 int array[MAX_NUM], array1[MAX_NUM], array2[MAX_NUM];
int sum[MAX_NUM];
int num;
int query_num;
bool filled; void cal_left(int pos, int array[])
{
for (int i = pos - ; i > ; i--)
array[i] = sum[i + ] - array[i + ] - array[i + ];
} void cal_right(int pos, int array[])
{
for (int i = pos + ; i <= num; i++)
array[i] = sum[i - ] - array[i - ] - array[i - ];
} void input()
{
int pos = -;
for (int i = ; i <= num; i++)
{
scanf("%d", &array[i]);
if (i % != && array[i] != -)
pos = i;
}
for (int i = ; i <= num; i++)
scanf("%d", &sum[i]);
array[] = ;
for (int i = ; i <= num; i += )
array[i] = sum[i - ] - (sum[i - ] - array[i - ]);
if (num % == && pos == -)
return;
filled = true;
if (array[num] != -)
array[num - ] = sum[num] - array[num];
if (array[num - ] != -)
array[num] = sum[num] - array[num - ];
if (array[num] != -)
cal_left(num, array);
array[num + ] = ;
if (pos != -)
{
if (array[pos - ] != -)
pos--;
cal_left(pos + , array);
cal_right(pos, array);
}
} void work()
{
scanf("%d", &query_num);
for (int i = ; i < query_num; i++)
{
int a;
scanf("%d", &a);
a++;
if (filled)
{
printf("%d\n", array[a]);
continue;
}
if (a % == )
printf("%d\n", array1[a]);
else if (a % == )
printf("%d\n", array2[a]);
else
printf("%d\n", array[a]);
}
} void make2()
{
memcpy(array2, array, sizeof(array2));
array2[] = ;
array2[] = sum[] - array2[];
cal_right(, array2);
array2[] -= *min_element(array2 + , array2 + num + );
array2[] = sum[] - array2[];
cal_right(, array2);
} void make1()
{
memcpy(array1, array, sizeof(array1));
array1[num] = ;
array1[num - ] = sum[num] - array1[num];
cal_left(num, array1);
array1[num] -= *min_element(array1 + , array1 + num + );
array1[num - ] = sum[num] - array1[num];
cal_left(num, array1);
} int main()
{
while (scanf("%d", &num) != EOF)
{
filled = false;
input();
if (!filled)
{
make2();
make1();
}
work();
}
return ;
}

2013 ACM/ICPC 长沙网络赛J题的更多相关文章

  1. 2013 ACM/ICPC 南京网络赛F题

    题意:给出一个4×4的点阵,连接相邻点可以构成一个九宫格,每个小格边长为1.从没有边的点阵开始,两人轮流向点阵中加边,如果加入的边构成了新的边长为1的小正方形,则加边的人得分.构成几个得几分,最终完成 ...

  2. 2013 ACM/ICPC 长春网络赛E题

    题意:给出一个字符串,要从头.尾和中间找出三个完全相等的子串,这些串覆盖的区间互相不能有重叠部分.头.尾的串即为整个字符串的前缀和后缀.问这个相同的子串的最大长度是多少. 分析:利用KMP算法中的ne ...

  3. 2013 ACM/ICPC 长春网络赛F题

    题意:两个人轮流说数字,第一个人可以说区间[1~k]中的一个,之后每次每人都可以说一个比前一个人所说数字大一点的数字,相邻两次数字只差在区间[1~k].谁先>=N,谁输.问最后是第一个人赢还是第 ...

  4. 2013 ACM/ICPC 长沙现场赛 A题 - Alice's Print Service (ZOJ 3726)

    Alice's Print Service Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice is providing print ser ...

  5. 2013 ACM/ICPC 长沙现场赛 C题 - Collision (ZOJ 3728)

    Collision Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge There's a round medal ...

  6. 2013 ACM/ICPC 杭州网络赛C题

    题意:驴和老虎,在一个矩阵的两个格子里,有各自的起始方向.两者以相同的速度向前移动,前方不能走时驴总是向右,老虎总是向左.他们不能超出矩阵边界也不能走自己走过的格子(但可以走对方走过的格子).如果不能 ...

  7. 2013 长沙网络赛J题

    思路:这题对于其他能退出所有值的情况比较好像,唯一不能确定的是XXOXXOXXOXX这个形式的序列,其中XX表示未知,O表示已知. 我们令num[1]=0,那么num[4]=sum[3]-sum[2] ...

  8. 2013 ACM/ICPC 成都网络赛解题报告

    第三题:HDU 4730 We Love MOE Girls 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4730 水题~~~ #include < ...

  9. hdu 4763 && 2013 ACM/ICPC 长春网络赛解题报告

    一个KMP的简单题 不过好久没用过这个东东了,今天写的时候花了很多时间: 只需要花点时间判断下所有的元素都相同的的情况就行了! #include<cstdio> #include<c ...

随机推荐

  1. Java基础-重写-子类重写父类中的方法后执行情况

    代码 public class Test { public static void main(String[] args) { Shape shape = new Circle(); System.o ...

  2. [NOIP2011] 提高组 洛谷P1315 观光公交

    题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2 ...

  3. groovy-位运算

    从Groovy 1.0 beta 10开始,Groovy支持位运算:<<. >>, >>>, |, &, ^, and ~. 下表列出了位运算的操作符 ...

  4. Spring学习4-面向切面(AOP)之schema配置方式

    一.通过Scheme配置实现AOP步骤(Spring AOP环境的环境与上篇博文 Spring接口方式相同)    步骤一.编写业务类: public class AspectBusiness {   ...

  5. --hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)

    解题思路: 多重背包:第 i 件物品有 j 个可用. 本题中 第 p[i] 类大米 有 c[i] 袋大米可买 ,故本题为多重背包. n(总钱数).m(种类) p[i] 单价 h[i] 重量 c[i] ...

  6. 关于使用客户端控件和jquery上传文件

    一.导入Jquery插件ajaxfileupload.js 下载地址:http://www.phpletter.com/Demo/AjaxFileUpload-Demo/ 使用方法: $.ajaxFi ...

  7. 在64位windows 7上安装汇编调试工具debug.exe的方法

    最近我在研究汇编,书中介绍的调试工具还是基于WinXP 32bit时代中自带debug.exe进行调试,但是64bit的Windows XP.Vista.Win7.Win8都已经不自带这个工具了,网上 ...

  8. UIGestureRecognizer ios手势识别温习

    1.UIGestureRecognizer介绍 手势识别在iOS上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性. iOS系统在3.2以后,为方便开发这使用一些常用的手势,提供了 ...

  9. Java JNI 编程进阶 实例+c++数据类型与jni数据类型转换

    原文:http://www.iteye.com/topic/295776 JNI一直以来都很少去关注,但却是我心中的一个结,最近这几天刚好手头有点时间,因此抽空看了一下这方面的东西,整理了一份文档,J ...

  10. 新浪微博客户端(32)-设置相册图片的contentMode

    DJStatusPhotoView.m #import "DJStatusPhotoView.h" #import "UIImageView+WebCache.h&quo ...