CodeForces-1016C Vasya And The Mushrooms(模拟+思维+二重前缀和 ) 解题报告

xzc 2019/4/7


这周周赛的C题:wyt学姐的恶意
  这道题周赛的时候就出思路了,但是觉得可能很不好写,20分钟写了个大概,处理了前缀后缀和以及二重前缀后缀和,没推完公式


vjudge链接
codeforces链接

题意:

  有一个蘑菇园,是一个2*n的方格地。每个格子里都有一颗蘑菇,蘑菇的生长速度不同。
  Vasya这个人一开始站在左上角那个格子里,他必须走到每个格子里去采蘑菇,并且不能停留,1秒移动到一个相邻的格子,并且迅速采了这个格子的蘑菇(时间忽略不计),然后马上离开。而且他必须经过每个格子1次
  一开始时间为蘑菇高度都为0。求这个人能采到蘑菇高度之和的最大值是多少。(左上角那株肯定是0)


输入:

  n
  a1 a2 … an(代表第一行每列蘑菇每秒生长的高度)
  b1 b2 … bn(代表第二行每列蘑菇每秒生长的高度)


输出:

  一个整数,表示他能采到蘑菇高度之歌的最大值


Sample


 input1

3
1 2 3
6 5 4

 output1

70

 input2

3
1 1000 10000
10 100 100000

 output2

543210

input3(不用谢我)

6
12 8 12 17 20 5
17 4 8 8 8 4

output3

705

input4(不用谢我)

6
16 20 18 7 14 2
17 12 4 10 7 4

output4

741

分析:

(以样例4为例)

列数 1 2 3 4 5 6
a(生长速度) 16 20 18 7 14 2
b(生长速度) 17 12 4 10 7 4

我们可以把每个位置用一个字母标号:

列数 1 2 3 4 5 6
a A B C D E F
b G H I J K L
  • 那么,根据题意,这个人一开始在A这里,他必须采了高度为0的蘑菇,然后马上向相邻的格子转移,他只能向下走或者向右走。
  • 那么,根据题目的要求,他每个格子只能走一次,如果他第一步向右边走到了B,那么他的路径就确定了,只能是A->B->C->D->E->F->L->K->J->I->H->G
  • 如果他第一步往下走,到了G,那么他下一步只能往右从G到H
  • 现在他到了H,他又有2种选择:向右走到I(A->G->H->I),或者向上走到B(A->G->H->B)
  • 如果他选的是从H到I,那么他的路径又确定了,只能是A->G->H->I->J->K->L->F->E->D->C->B
  • 如果他选的是从H到B,那么他下一步只能往右从B到C
  • 现在他到了C,他又有两种选择:向右走到D(A->G->H->B->C->D),或者向下走到I(A->G->H->B->C->I)
  • 如果他选的是从C到D,那么他他的路径叒确定了,只能是A->G->H->B->C->D->E->F->L->K->J->I
  • 如果他选的是从C到I,那么下一步他只能往右到J,继续走蛇形…
  • (你懂我意思了吧)

所以,我们的思路就确定了,他能走的路线不多,少于2*n条,所以,我们可以用每条路线的答案ans去更新最终的结果res
我们可以这样写:
  循环的主线是让他走蛇形A->G->H->B->C->I->J->D->E->K->L->F
  在走这条主线的时候,在每个位置,如果该上下了他却往右走了,那么他的路径就确定了,我们计算一下他开小差走的其它路径的答案,更新一下结果,然后继续走蛇形
  那么问题来了,循环主线复杂度是O(2*n)的,我们能否O(1)或者O(logn)地求出图中每个点“开小差”后的结果呢?
我们就想到了前缀和


我们来模拟一下某一条路:
假如我们走蛇形,走到第4列J的位置,此时的时间t=7,我们本应该向上走到D,但是我们从J向右走到了K,那么后面的路就是(A->G->H->B->C->I->J)->K->L->F->E->D
那么我们如何计算从K到D这一段蘑菇的高度(设为h)呢?
我们可以暴力地算一遍:
h = 8*K + 9*L + 10*F + 11*E + 12*D
那么,我们可以先从J和L开始计时,把h表示为:
h = (1+7)*K + (2+7)*L + (1+9)*E + (2+9)*D

那么,7和9是怎么来的呢?
设J所在列数为i,则i = 4
7 = t
10 = 7+6-4 = t+n-i
那么h就可以表示为:

  t * (b[i]+b[i+1]+...+b[n])  -------------------->(1)
+ b[i]*1 + b[i+1]*2 + ... + b[n]*(n-i+1) --------->(2)
+ (t+n-i) * (a[n]+a[n-1]+a[n-1]+...+a[i])--------->(3)
+ a[n]*1 + a[n-1]*2 + ... + a[i]*(n+1-i) --------->(4)

那我们要如何求这4个式子呢?

  • 显然(1)(3)可以用数组a,b的前缀和(后缀和更好)
  • 那么(2)(4)怎么求呢?
  • 注意了!(2)不就是数组b后缀和的后缀和吗?
        (4)不就是数组a前缀和的前缀和吗?

我们可以预处理之后O(1)算出来(1)(2)(3)(4)

至此,这题可以做了,而且复杂度为O(n)
我们先定义几个数组
sumaL: a数组的前缀和
sumaR: a数组的后缀和
sal : a数组前缀和的前缀和
sar : a输入后缀和的后缀和
(b的同理)


上代码:

/*
Author: XuZhichao
Status: Accepted   Time: 124ms
Memory: 23512kB    Length: 1864
Lang: GNU G++11 5.1.0
Submitted: 2019-04-07 00:53:49
*/
#include <bits/stdc++.h>
#define Mst(a,b) memset(a,(b),sizeof(a))
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 3e5 + 100;
LL a[maxn],b[maxn],res;
LL sumaL[maxn],sumaR[maxn],sumbL[maxn],sumbR[maxn];
LL sal[maxn],sar[maxn],sbl[maxn],sbr[maxn];
void downToRight(LL ans,int i,int n,LL t)
{ans += t*sumbR[i+1]+sbr[i+1]+(t+n-i)*sumaR[i]-sal[i-1]+sal[n]-sumaL[i-1]*(n-i+1);res = max(res,ans);
}
void upToRight(LL ans,int i,int n,LL t)
{ans += t*sumaR[i+1]+sar[i+1]+(t+n-i)*sumbR[i]-sbl[i-1]+sbl[n]-sumbL[i-1]*(n-i+1);res = max(res,ans);
}
int main()
{//freopen("in.txt","r",stdin);int n;int ca = 0;while(scanf("%d",&n)!=EOF){if(ca++){sumaL[0] = sumaL[n+1] = 0;sumbL[0] = sumbL[n+1] = 0;sumaR[0] = sumaR[n+1] = 0;sumbL[0] = sumbR[n+1] = 0;sal[0] = sal[n+1] = 0;sar[0] = sar[n+1] = 0;sbl[0] = sbl[n+1] = 0;sbr[0] = sbr[n+1] = 0;}For(i,1,n) scanf("%lld",a+i),sumaL[i] = sumaL[i-1]+a[i];For(i,1,n) scanf("%lld",b+i),sumbL[i] = sumbL[i-1]+b[i];if(n==1){printf("%lld\n",b[1]);continue;}Rep(i,n,1) sumaR[i] = sumaR[i+1]+a[i],sumbR[i] = sumbR[i+1]+b[i];For(i,1,n) sal[i]  = sal[i-1]+sumaL[i], sbl[i] = sbl[i-1]+sumbL[i];Rep(i,n,0) sar[i]  = sar[i+1]+sumaR[i], sbr[i] = sbr[i+1]+sumbR[i];res = 0;res = sar[2]+sbl[n]+sumbL[n]*(n-1);LL t = 0;LL ans = 0;For(i,1,n)  {++t;if(i&1) ans += t*b[i];else ans += t*a[i];if(i==n) {res = max(res,ans);continue;}++t;if(i&1){ans += t*b[i+1];if(i<n-1)downToRight(ans,i+1,n,t); }else{ans += t*a[i+1];if(i<n-1)upToRight(ans,i+1,n,t);}}printf("%lld\n",res);}return 0;
}

CodeForces-1016C Vasya And The Mushrooms(模拟+思维+前缀和的前缀和) 解题报告 Apare_xzc相关推荐

  1. codeforces 1016C - Vasya And The Mushrooms 【构造 + 思维】

    题目链接:戳这里 题意:从(1,1)出发,一遍把格子走完,每个格子只能走一次.问怎么走总和最大. 解题思路:画图可知,总共就3种走法的混合. dw: 样例1的走法 up: 样例1反过来的走法 lp: ...

  2. 1016C. Vasya And The Mushrooms

    可以知道有两种走法 一种是蛇形上下移动 另一种是直接移动到底再转回来 那么可以先处理三种走法(走到底的情况分为从上开始和从下开始)在每个点的值,再加起来找出最大值 很有趣的是:走到底的情况要走的相对顺 ...

  3. [JZOJ4274] [NOIP2015模拟10.28B组] 终章-剑之魂 解题报告(二进制)

    Description [背景介绍] 古堡,暗鸦,斜阳,和深渊-- 等了三年,我独自一人,终于来到了这里-- "终焉的试炼吗?就在这里吗?"我自言自语道. "终焉的试炼啊 ...

  4. [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)

    题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城 ...

  5. 【CodeForces - 1051C 】Vasya and Multisets (模拟)

    题干: Vasya has a multiset ss consisting of nn integer numbers. Vasya calls some number xxnice if it a ...

  6. cf Educational Codeforces Round 48 C. Vasya And The Mushrooms

    原题: C. Vasya And The Mushrooms time limit per test2 seconds memory limit per test256 megabytes input ...

  7. Codeforces Round #249 (Div. 2) (模拟)

    Codeforces Round #249 (Div. 2) (模拟) C. Cardiogram time limit per test 1 second memory limit per test ...

  8. 【CodeForces - 798D】Mike and distribution (思维构造,贪心,黑科技)

    题干: Mike has always been thinking about the harshness of social inequality. He's so obsessed with it ...

  9. 【CodeForces - 155C】Hometask (字符串,思维,贪心,熟悉句式)(总结)

    题干: Sergey attends lessons of the N-ish language. Each lesson he receives a hometask. This time the ...

最新文章

  1. 20165328 预备作业3 Linux安装及命令
  2. 添加服务引用的本质是什么?
  3. 记录一次CPLD资源过少、时序伪例的解决办法
  4. Oracle 安装完怎么用,oracle 11g 安装完怎么用
  5. linux 端口 镜像吗,Linux如何实现镜像端口
  6. camuda流程引擎如此简单「五」
  7. 每天一道LeetCode-----将字符串切分成若干单词,使得每个单词都在给定的字典中,求出所有的切分结果
  8. 实现“Please wait...”效果
  9. vue中的keep-alive
  10. 【电脑帮助】解决Wind10系统修改电脑默认用户名Administrator的问题
  11. ir2104驱动电路原理
  12. Linux:搭建GIT服务,Linux中使用git,git基础命令,和原理
  13. 【《操作系统慕课版》合集】期末复习 + 核心算法整理 + 课后答案
  14. 匈牙利命名法的衰落和建议
  15. 23北大软微408经验贴(含初试+复试)
  16. 提高代码速度的“正确姿势”
  17. 小巧灵活的奇瑞小蚂蚁带你出行
  18. Iperf测试服务器上下行带宽
  19. 关于Git中fetch和pull区别为
  20. tencent腾讯——面试

热门文章

  1. [转载]以xilinx为例的低功耗设计
  2. 医保卡和社保卡的区别
  3. 【iOS】调用百度、高德地图SDK
  4. 灿谷集团荣获“公益践行奖”
  5. MyBatis关联对象查询
  6. odbc建oracle dsn,Linux平台配置Oracle ODBC DSN的方法
  7. CPU中的通用寄存器
  8. 如何将谷歌浏览器的插件下载到本地?
  9. gitlab 生成ssh密匙
  10. linux cuda安装目录,ubuntu16.04上的cuda安装、卸载以及替换