2013 ACM/ICPC Asia Regional Changsha Online - J
原题戳这里。
题意: 有一未知列数a1,a2,a3.....an,
已知s[i]=a[i-1]+a[i]+a[i] (1<i<n)
s[1]=a[1]+a[2];
s[n]=a[n-1]+a[n]
还知道a数列中一些数的值(可以全部不知道)
询问一些数 可能的最大值是多少。
首先,可以根据s数组求出a[i]的值(i为3 的倍数) answer[3k]=s[3k-1]-s[3k-2]+a[3k-3];
其次,要是知道连续两个数a[i] ,a[i+1],或者a[i],a[i+1],那么就能确定整个序列。,问题解决,直接回复 询问即可。
最后,要是不能确定整个序列,那么所有a[i]都是未知的(i不为3 的倍数)。下面求这些未知a[i]的可能最大值。
求a中i=3k+1位上的最大值
1.设a[1]=s[1],则a[2]=0;
2.根据a[i]=s[i-1]-a[i-1]-a[i-2],暂时求出一个可能非法(出现负值)的序列temp。
3.找到i=3k+2位上的最小值min(min<=0) (min必不大于0是因为a[2]=0)
4.为了让a[3k+2]上的数合法,把temp[3k+1] 的数降低-min(min为负数),temp[3k+1]的数上升-min。
这样temp就合法,且temp[3k+1]为最大,temp[3k+2]为最小,取temp[3k+1]作为3k+1位上的答案。
answer[3k+1]=temp[3k+1]+min;
求a中i=3k+2位上的最大值
1.设a[1]=0;a[2]=s[1];
2.上同
3.找到i=3k+1位上的最小值min
4.answer[3k+2]=temp[3k+2]+min;
一个answer数组就能离线地处理这些询问了。
PWW学姐问这么算出来为什么是最大而且合法的,当初给她的解释是在求i=3k+1时,先把temp[3k+1]做成最大,temp[3k+2]略显非法,(这时temp[3k+1]肯定是最大的),同时把temp[3k+1]做最小地牺牲(即降低一个值),使得temp[3k+2]也是合法的。同时这个牺牲显然也是最小的。所以temp[3k+1]经过调整后肯定是最大的。因为是最大的,所以temp[3k+1]肯定是非负的,否则肯定是数据错了。
当然这样是毛估估的。。。(懂“毛估估”这个词么?就是在简单得在心里蹭蹭。“蹭蹭”:=“想一想”)
证明最大性质的证明过程:
假设在3k+1这个位置的最大值不是temp[3k+1] ,而是m,则设dis=m-temp[3k+1] (dis>0)。
此时在3k+2这个位置的值应该为temp[3k+2]-dis (temp[3k+1]+temp[3k+2] 为定值)
同理3k+4,这个位置的值应该为temp[3k+2]+dis (temp[3k+2]+temp[3k+4]为定值)
即每个位置的值是temp中所有3k+1位加dis,3k+2位减dis.
而temp[3k+2]至少有一个数为0(算法流程里体现了),这是这个位置的数为-dis,负数,矛盾,非法,不成立。
证毕。
PS:看到我的两个小队友的blog了,感觉略感落伍,以前以为大牛才能有blog。谨以此文,纪念我的第一篇公开解题报告。
代码略难看。。。(羞涩)
#include <stdio.h>
#include <string.h>
#define MAXN 100005
#define max(a,b) a>b? a:b
int n,m;
int tell[MAXN],s[MAXN];
int query[];
int a[MAXN];
int ansmax[MAXN],ansmin[MAXN];
int temp[MAXN];
void fuck() //这种情况最恶心了,比赛就是写这种情况来不及了。。诅咒之
{
temp[]=s[];// 3k+1位最大
temp[]=;
int i;
for (i =; i<=n; i++)
temp[i]=s[i-]-temp[i-]-temp[i-];
int min=0x7ffffff;
for (i=; i<=n; i=i+)
if (min > temp[i])
min = temp[i];
for (i=; i<=n; i=i+)
ansmax[i]=temp[i]+min;
temp[n]=s[n];//3k+2位最大
temp[n-]=;
for (i =n-; i>=; i--)
temp[i]=s[i+]-temp[i+]-temp[i+];
min=0x7ffffff;
for (i=; i<=n; i=i+)
if (min > temp[i])
min = temp[i];
for (i=; i<=n; i=i+)
ansmax[i]=temp[i]+min;
for (i = ; i<n; i=i+)
ansmax[i]=temp[i];
ansmax[n]=max(ansmax[n],temp[n]+min);
for (i=; i<=m; i++)
printf("%d\n",ansmax[query[i]+]);
}
void work()
{
int i=,j=,k;
memset(a,-,sizeof(a));
a[]=;
while (j<=n) //顺序3k位置的值
{
a[j] = s[j-]-s[j-]+a[j-];
j+=;
}
j = n-;
a[n+]=;
while ( j>=) //逆序3k位置的值
{
a[j] = s[j+]-s[j+] +a[j+];
j-=;
}
for (i=; i<=n; i++)
if (tell[i] != -)
a[i]=tell[i];
int flag=true;
printf("\n");
for (i= ;i+ <= n; i++) //a[i],a[i+2]已知,求a[i+1]
if ( a[i] != - && a[i+] != -)
a[i+]=s[i+]-a[i]-a[i+];
for ( i = ; i <n && flag; i++)//检测是否有连续两个数存在的情况
if (a[i]!= - && a[i+] !=-)
{
flag=false;
j=i;
for (k=i-; k>=; k--)
a[k] =s[k+]-a[k+]-a[k+];
for (k=i+; k<=n; k++)
a[k]= s[k-]-a[k-]-a[k-];
}
if (!flag) //如果有就ok了
for (k=; k<=m; k++)
printf("%d\n",a[query[k]+]);
if ( flag )//没有连续两个数。
fuck();
int main()
{
int i,j;
while (scanf("%d",&n)!=EOF)
{
for (i=; i<=n; i++)
scanf("%d",&tell[i]);
for (i=; i<=n; i++)
scanf("%d",&s[i]);
scanf("%d",&m);
for (i=; i <=m; i++)
scanf("%d",&query[i]);
work();
}
return ;
}
2013 ACM/ICPC Asia Regional Changsha Online - J的更多相关文章
- 2013 ACM/ICPC Asia Regional Changsha Online J Candies
AC了,但是不知道为什么,但是恶心的不得了~最近写代码,思路都非常清晰,但是代码各种bug~T.T~说说思路吧:二分~330ms~ 小队友fribbi的思路是离线250msAC~ 预处理solve函数 ...
- 2013 ACM/ICPC Asia Regional Changsha Online G Goldbach
比赛的时候,被题目误导了,题目最后说结果可能很大,要取模,那时就想直接求会TLE的!!! 赛后才知道,坑啊………… 代码如下: #include<iostream> #include< ...
- 2013 ACM/ICPC Asia Regional Changsha Online - G(DP)
第一眼就想到DP,然后想了N久就想不到可以不重算的DP 最后没办法了 先算出来 再去重.. 因为最多只有三个 对于三个来说有三种组合情况 x+y+z, x*y*z, x*y+z 那要么 x,y,z都 ...
- [2013 ACM/ICPC Asia Regional Hangzhou Online J/1010]hdu 4747 Mex (线段树)
题意: + ;];;;], seg[rt << | ]);)) * fa.setv;) * fa.setv;;], seg[rt << | ], r - l + );;, ...
- 2013 ACM/ICPC Asia Regional Changsha Online - C Color Representation Conversion
这个纯粹是一个细节题啊!!! 由于某个地方的浮点数比较写错了,WA了无数次啊…… 代码如下: #include<iostream> #include<cstdio> #incl ...
- 2013 ACM/ICPC Asia Regional Changsha Online - E
第一个被板刷的题 取余 依次算在周几 #include <iostream> #include<cstdio> #include<cstring> #include ...
- 2013 ACM/ICPC Asia Regional Changsha Online–C (模拟)
题目描述 略... 题解 注意控制精度即可....变量全部定义成double,结果round就行....妈蛋....被这题目恶心死了.... 代码: #include <iostream> ...
- 2013 ACM/ICPC Asia Regional Changsha Online – C题 Color Representation Conversion (坑爹模拟题)
题意:给你三种颜色表示模式,RGB,HSV和HSL,实现任意模式之间两两转化. 1.最好别看题目中给的转化公式描述,我觉得叙述的一点也不清楚,看维基百科,把维基百科上的公式一句一句翻译过来就好 2.在 ...
- hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...
随机推荐
- Android组件化最佳实践 ARetrofit原理
ARetrofit原理讲原理之前,我想先说说为什么要ARetrofit.开发ARetrofit这个项目的思路来源其实是Retrofit,Retrofit是Square公司开发的一款针对Android网 ...
- 零基础转行Linux云计算运维工程师获得20万年薪的超级学习技巧
云计算概念一旦产生便一发不可收拾,成为移动互联网时代最为火热的行业之一.国内各大互联网公司例如阿里.腾讯.百度.网易等纷纷推出自己的云计算产品,3月10日,腾讯云0.01元投标时间更是让云计算在普罗大 ...
- php第十三节课
查询 <?php class DBDA{ public $host = "localhost"; //数据库地址 public $uid = "root" ...
- C++ 中 字符数组 和 指针 区别
char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; c ...
- ThinkPHP5.1安装
安装 ====== 按照官方的推荐方式,推荐使用composer方式安装 TP5.1环境要求 PHP >= 5.6.0 PDO PHP Extension MBstring PHP Extens ...
- git 的简单使用(2)
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了: $ rm test.txt 你可以使用 git rm test.txt来删除 然后用git commit -m " ...
- Git:分支的创建、合并、管理和删除
了解分支 如果想实现多人协作.划出Bug区.Feature区等功能,就需要分支功能.(确实很强大的地方) 每次commit时,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条 ...
- 8.1.3 Row对象
假设数据以下面的方式创建并插入数据: import sqlite3 conn = sqlite3.connect(r'D:\test.db') c = conn.cursor() c.execute( ...
- FORTIFY_SOURCE
In recent years Linux distributions started treating security more seriously. Out of many security f ...
- kendo Grid的toolbar自定义
由于这个toolbar官方进增加了create,save还有一个是_____ 所以想要自定义话就需要使用 下面的代码(这个是MVVM模式) data-toolbar='[{ template: Ken ...