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

分析:设数列为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. Ajax、反向Ajax和WebSocket 概念

    Ajax 异步的JavaScript和XML(Asynchronous JavaScript and XML,Ajax),一种可通过JavaScript来访问的浏览器功能特性,其允许脚本向幕后的网站发 ...

  2. 【CodeForces 297C】Splitting the Uniqueness

    题意 序列s有n个数,每个数都是不同的,把它每个数分成两个数,组成两个序列a和b,使ab序列各自去掉个数后各自的其它数字都不同. 如果存在一个划分,就输出YES,并且输出两个序列,否则输出NO. 分析 ...

  3. ci连贯操作的limit两个参数和sql是相反的

    ci连贯操作的limit两个参数和sql是相反的 db->where("name =",'mary')->ge() name后面要有个空格否则报错当为一个字段 -> ...

  4. HTML 5 应用程序缓存

    使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本. 什么是应用程序缓存(Application Cache)? HTML5 引入了应用程序缓存,这 ...

  5. 设置button不同状态下的背景色,即把这个颜色变成图片设置成,背景图片

    - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state { [self setBack ...

  6. 锋利的jQuery-3--用js给多选的checkbox或者select赋值

    单选的select: <select id="single"> <option>Single</option> <option>Si ...

  7. 锋利的jQuery-1-- :的用法

    在一个id为table的表格的tbody中,如果每一行的最后一列的checkbox没有被禁用,则把这行的背景色设置为红色. $( "#table>tbody>tr:has(td: ...

  8. DOM-based xss

    这个漏洞往往存在于客户端脚本,如果一个Javascript脚本访问需要参数的URL,且需要将该信息用于写入自己的页面,且信息未被编码,那么就有可能存在这个漏洞. (一)DOM—based XSS漏洞的 ...

  9. C# 获取时间差(几天前,几小时前,几分钟前,几秒前)

    #region 获取时间差string GetTime(BsonString getTime) /// <summary> /// 获取时间差 /// </summary> / ...

  10. iOS多线程介绍

    一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...