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

分析:设数列为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. codevs1227 方格取数2 注意数组啊啊啊啊啊啊啊啊啊啊

    一开始T了一组RE了一组,实在找不出错来,就把数组加了一个0竟然就多A了一组.很惊讶的又加了几个0最后竟然全A了!!! 懒得做了,改的是之前的那个蚯蚓的游戏问题.还是需要拆点,至于为什么不能重复走结点 ...

  2. Java设计模式-迭代子模式(Iterator)

    顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松.这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对 ...

  3. SP*

    1.PS1——默认提示符 root@tcx2250-14:/etc# echo $PS1\u@\h:\w\$ \u是用户名 \h是主机名 \w是当前目录的完整路径.请注意当你在主目录下的时候,如上面所 ...

  4. 【转】mac os x系统上Android开发环境的搭建

    由于Google官方已经不提供Adt-Bundle下载了,主推AndroidStudio.可以从这个链接下载http://www.androiddevtools.cn.上面不光有adt-bundle, ...

  5. Oracle查看锁表

     查看锁表进程SQL语句1: select sess.sid,     sess.serial#,     lo.oracle_username,     lo.os_user_name,     a ...

  6. BIEE连接数据库的方法

    BI创建(数据)分析.仪表盘.报表前,都需要对数据进行建模,在oracle biee里称为创建“资料档案库”-该文件后缀为RPD,所以一般也称为创建RPD文件. 步骤: 1.从windows开始菜单里 ...

  7. hive 使用笔记(partition; HDFS乱码)

    6.  insert 语句 1) 因为目标表有partition, 所以刚开始我使用的语句是 insert overwrite table sa_r_item_sales_day_week_month ...

  8. 9.Android之日期对话框DatePicker控件学习

    设置日期对话框在手机经常用到,今天来学习下. 首先设置好布局文件:如图 xml对应代码 <?xml version="1.0" encoding="utf-8&qu ...

  9. JAVA中toString方法的作用

    因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不 ...

  10. 51NOD 1400 序列分解

    传送门:1400 序列分解序列分解 基准时间限制:1s  空间限制:131072 KBKB131072 KB 1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题1 秒 空间限制:13 ...