CF1474-D. Cleaning

题意:

给出一个长度为\(n\)的正整数序列,你可以对序列进行如下操作:

  • 对序列中相邻的两个数字\(a_{i}, a_{i+1}\)同时减去一个数字\(t(t<=min(a_{i},a_{i+1}))\)。

现在你有一次机会可以将序列中任意两个相邻的数字交换位置(可以不交换)。问你可不可以通过上述操作将序列中所有数字都减为\(0\)。


题解:

在说具体做法之前,先考虑三个事情:

1. 先不考虑交换数字,在不交换数字的情况我们要把序列中全部的数字都消为\(0\)(当然也可能不能全部消为0)可以通过什么方法呢?可以通过以下两种操作获得:

首先我们假设在\(a_1\)的前面有一个\(a_0=0\),那么消除的过程就是\(a_1=a_1-a_0, a_2=a_2-a_1,..., a_n=a_n-a_{n-1}\),这样顺利的话就可以把全部的数字消掉。

或者我们假设在\(a_n\)的后面有一个\(a_{n+1}=0\),那么过程为\(a_n=a_n-a_{n+1}, a_{n-1}=a_{n-1}-a_n,..., a_1=a_1-a_2\),同样也可以把全部的数字都消掉。

上述操作为顺利情况下消除的过程,但实际上并不一直是那么的顺利。以上述的第一种操作为例,假如有\(a_{i-1}>a_{i}\),那么就会出现\(a_{i}<0\)的情况,这显然是不可能的,同样第二种操作也可能会出现这种情况。

2. 如果从前往后减,那么在交换了\(a_{i},a_{i-1}\)这两个数字之后会不会对\(a_{i-1}\)之前的数字造成影响呢?同样的从后往前减,交换\(a_{i},a_{i+1}\)之后会不会对\(a_{i+1}\)之后的数字造成影响呢?这两个问题的答案是否定的,均不会造成影响。

3. 对于一个序列,假设现在这个序列可以从前往后把所有数字都消掉,那么先从前往后消掉一部分,那么可不可以从后往前把剩下的一部分全部消掉呢?再假设这个序列不能从前往后或从后往前把全部数字消掉,那么能不能通过先从前往后消掉一部分再从后往前消掉另一部分把整个序列消掉?

换句话说,对于一个序列而言,先从前往后消去一部分,再从后往前消去另一部分,是否和只从前往后或只从后往前消除是等效的呢(能全部消掉或不能)?答案是肯定的,这也是本题的关键。


前面作了那么多铺垫,现在说一下做法。先定义两个数组\(pre(prefix)\)和\(suf(suffix)\),\(pre[i]\)表示从前往后消掉了\(a_{1}, a_{2},..., a_{i-1}\)之后\(a_{i}\)的值,\(suf[i]\)表示从后往前消掉了\(a_{n}, a_{n-1},...,a_{i+1}\)之后\(a[i]\)的值。这里说一下,不论是从前往后还是从后往前,如果\(a_{i}\)减完之后得到了一个负数,那么他之后的所有数字不论是正是负都没有意义了,所以\(a_{i}\)以及\(a_{i}\)之后所有数字就需要用一个特殊的标记这个\(pre\)或\(suf\)是无效的。

现在就可以枚举交换的数字了,比如现在要枚举的是交换\(a_{i}\)和\(a_{i+1}\),那么只需要看\(pre[i-1],a[i+1],a[i],suf[i+2]\)这几个数字构成的序列可不可以通过从前往后或者从后往前给全部消掉即可,如果可以答案就是\(YES\),后面也就不用继续枚举了;如果全部枚举之后都不能那么答案就是\(NO\)。当然这有个前提就是\(pre[i-1]\)和\(suf[i+2]\)不能是无效的,也就是不能是你之前打过特殊标记的。


AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector> void solve() {
int n;
scanf("%d", &n);
std::vector<int>a(n + 2);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
std::vector<int>pre(n + 2), suf(n + 2);
for (int i = 1; i <= n; i++) {
if (pre[i - 1] == -1 || a[i] < pre[i - 1]) {
pre[i] = -1;
} else {
pre[i] = a[i] - pre[i - 1];
}
}
if (pre[n] == 0) {
printf("YES\n");
return;
}
for (int i = n; i > 0; i--) {
if (suf[i + 1] == -1 || a[i] < suf[i + 1]) {
suf[i] = -1;
} else {
suf[i] = a[i] - suf[i + 1];
}
}
for (int i = 0; i <= n - 2; i++) {
int l = i, r = i + 3;
if (pre[l] == -1 || suf[r] == -1) {
continue;
}
if (a[r - 1] >= pre[l] && a[l + 1] >= suf[r] && a[r - 1] - pre[l] == a[l + 1] - suf[r]) {
printf("YES\n");
return;
}
}
printf("NO\n");
} int main() {
int T;
scanf("%d", &T);
while(T--) {
solve();
} return 0;
}

小结:

本题本质上就是暴力,只不过\(O(n^2)\)的暴力是不能接受的,所以先对原来数据进行预处理,使得最终时间复杂度从\(O(n^2)\)减为\(O(n)\)。

CF1474-D. Cleaning的更多相关文章

  1. 【bzoj1672】[USACO2005 Dec]Cleaning Shifts 清理牛棚

    题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now ...

  2. Coursera-Getting and Cleaning Data-week1-课程笔记

    博客总目录,记录学习R与数据分析的一切:http://www.cnblogs.com/weibaar/p/4507801.html -- Sunday, January 11, 2015 课程概述 G ...

  3. Coursera-Getting and Cleaning Data-Week2-课程笔记

    Coursera-Getting and Cleaning Data-Week2 Saturday, January 17, 2015 课程概述 week2主要是介绍从各个来源读取数据.包括MySql ...

  4. Coursera-Getting and Cleaning Data-Week3-dplyr+tidyr+lubridate的组合拳

    Coursera-Getting and Cleaning Data-Week3 Wednesday, February 04, 2015 好久不写笔记了,年底略忙.. Getting and Cle ...

  5. Coursera-Getting and Cleaning Data-week4-R语言中的正则表达式以及文本处理

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html Thursday, January 29, 2015 补上第四周笔记,以及本次课程总结. 第四周 ...

  6. 【BZOJ1672】[Usaco2005 Dec]Cleaning Shifts 清理牛棚 动态规划

    [BZOJ1672][Usaco2005 Dec]Cleaning Shifts Description Farmer John's cows, pampered since birth, have ...

  7. poj 2376 Cleaning Shifts

    http://poj.org/problem?id=2376 Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  8. POJ 2376 Cleaning Shifts(轮班打扫)

    POJ 2376 Cleaning Shifts(轮班打扫) Time Limit: 1000MS   Memory Limit: 65536K [Description] [题目描述] Farmer ...

  9. POJ 2376 Cleaning Shifts 贪心

    Cleaning Shifts 题目连接: http://poj.org/problem?id=2376 Description Farmer John is assigning some of hi ...

  10. Bzoj 3389: [Usaco2004 Dec]Cleaning Shifts安排值班 最短路,神题

    3389: [Usaco2004 Dec]Cleaning Shifts安排值班 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 218  Solved: ...

随机推荐

  1. cobalt strike出现连接超时情况解决办法

    服务器安装好teamserver服务后,进行连接,此时出现了连接超时的情况 检查方法: 一.检查端口是否正常开启 netstat -an | grep <设置的端口号>centos7可以用 ...

  2. k8s中教你快速写一条yaml文件

    一条yaml中有很多字段,如果去背这些字段,其实也能背过,但是去写一条yaml,也往往浪费很多的时间,也会出错,其实我们可以用一条命令就能快速来写一段自定义的yaml,工作中去修改相应的yaml也得心 ...

  3. C# 中的动态类型

    翻译自 Camilo Reyes 2018年10月15日的文章 <Working with the Dynamic Type in C#> [1] .NET 4 中引入了动态类型.动态对象 ...

  4. 发票校验BAPI_INCOMINGINVOICE_CREATE

    CALL FUNCTION 'BAPI_INCOMINGINVOICE_CREATE'    EXPORTING      headerdata                = headerdata ...

  5. DOCKER 安装步骤-最靠谱的笔记

    一.系统环境规划 服务器名 项目名称 docker 操作系统 CentOS Linux release 7.1.1503 (Core) Docker 版本 17.03.2-ce   二.Docker ...

  6. 1.2V升压到3V和3.3V的升压芯片

    1.2V镍氢电池升压到3V和3.3V输出,1.2V升压3V,1.2V升压3.3V稳压输出供电的芯片. PW5100 是一款低静态电流.达效率. PFM 模式控制的同步升压变换器. PW5100 所需的 ...

  7. vue+element-ui:table表格中的slot 、formatter属性

    slot 插槽,table中表示该行内容以自定义方式展示 :formatter 方法,用来格式化内容 Function(row, column, cellValue, index) html < ...

  8. Scrapy———反爬蟲的一些基本應對方法

    1. IP地址驗證 背景:有些網站會使用IP地址驗證進行反爬蟲處理,檢查客戶端的IP地址,若同一個IP地址頻繁訪問,則會判斷該客戶端是爬蟲程序. 解決方案: 1. 讓Scrapy不斷隨機更換代理服務器 ...

  9. 主题模型(Topic)

    消息队列 RocketMQ - 打造金融级消息服务 - 阿里云 https://www.aliyun.com/product/rocketmq 主题模型(Topic) 发布/订阅(Pub/Sub) 一 ...

  10. Windows 10 安装 JDK14 Java 环境,没有 jre 包

    一.下载 JDK Oracle JDK 官网下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html 二.配置环 ...