[MdOI2020] Decrease

古老的博文。

今天巨佬团队 \(\texttt{luogu}\) 公开赛中的第三题,当时我写了好久才想到暴力做法 \(\texttt{42分}\),后来我还很离谱的写了个二维线段树,最终也没做出来。看来我还是太蒻了。

其实此题的做法是:简单差分

审题很重要,按照题目描述输入矩阵,题目中也说了,要快读:

for(int i=1,x,y,z;i<=m;i++){
x=d(),y=d(),z=d();
a[x][y]=z;
}

暴力做法:枚举覆盖正方形的左上角,暴力覆盖。 代码:

int main(){
n=d(),m=d(),k=d();
for(int i=1,x,y,z;i<=m;i++){
x=d(),y=d(),z=d();
a[x][y]=z;
}
for(int i=1;i<=n-k+1;i++)
for(int j=1;j<=n-k+1;j++)
if(a[i][j]!=0){
ans+=abs(a[i][j]);
int tmp=a[i][j];
for(int x=i;x<=i+k-1;x++)
for(int y=j;y<=j+k-1;y++)
a[x][y]-=tmp;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]!=0) return puts("-1"),0;
printf("%lld\n",ans);
return 0;
}

这么蒟蒻的做法,我拿到了 \(\texttt{42分}\),可见暴力的重要性。

然后我们发现,修改的区间一定是一个矩形,而且是增减修改,并且是统一修改,就应该想到用差分。把每行单独拎出来差分一下,形成差分数组 \(cf[][]\):

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cf[i][j]=a[i][j]-a[i][j-1];

然后暴力枚举覆盖正方形左上角端点,如果不为零就把整个右下角的 \(k\times k\) 矩阵减去左上角端点的数,然后让 \(\texttt{ans}\) 加上左上角端点数的绝对值。因为当枚举到一个端点的时候,它同一行左端的端点肯定被清零了,所以到这个端点时这个端点的值就是 \(cf[][]\) 了。代码:

for(int i=1;i<=n-k+1;i++)
for(int j=1,num=0;j<=n-k+1;j++){
num=cf[i][j];
if(num!=0){
ans+=abs(num);
for(int t=i;t<=i+k-1;t++)
cf[t][j]-=num,cf[t][j+k]+=num; //k*k矩阵修改通过差分优化,时间复杂度为O(n)
}
}

因为要覆盖的左端点少,所以这样的代码时间复杂度是合理的。

题目中说还有“无法使矩阵中所有数都变为 \(0\)”的情况,所以最后再 \(n\times n\) 暴力扫一遍差分矩阵,如果还有没清零的数,就 \(\texttt{puts("-1")}\)。代码:

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(cf[i][j]) return puts("-1"),0;

就这么简单,普及难度,可是我比赛时缺没想到。如果你懂了,那么蒟蒻就放代码了:

#include <bits/stdc++.h>
using namespace std;
#define lng long long
namespace rd{
const int L=1<<16;
char buf[L],*S,*T;
inline char Gc_(){
if(S==T){T=(S=buf)+fread(buf,1,L,stdin);
if(S==T) return EOF;}
return *S++;
}
inline char Gc(){return getchar();}
inline int d(){
char c;int f=1,x;
for(c=Gc();c>'9'||c<'0';c=Gc())
if(c=='-') f=-1;
for(x=0;c>='0'&&c<='9';c=Gc())
x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
}using namespace rd;
const int N=5e3+10;
int n,m,k,a[N][N];
lng ans;
int cf[N][N];
int main(){
n=d(),m=d(),k=d();
for(int i=1,x,y,z;i<=m;i++){
x=d(),y=d(),z=d();
a[x][y]=z;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cf[i][j]=a[i][j]-a[i][j-1];
for(int i=1;i<=n-k+1;i++)
for(int j=1,num=0;j<=n-k+1;j++){
num=cf[i][j];
if(num!=0){
ans+=abs(num);
for(int t=i;t<=i+k-1;t++)
cf[t][j]-=num,cf[t][j+k]+=num;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(cf[i][j]) return puts("-1"),0;
printf("%lld\n",ans);
return 0;
}

祝大家学习愉快!

题解-Decrease的更多相关文章

  1. 题解 【[MdOI2020] Decrease】

    \[ \texttt{Preface} \] 感觉 C 比 B 还简单? \[ \texttt{Description} \] 给定一个 \(n×n\) 的矩阵,你可以进行若干次操作. 每次操作,你可 ...

  2. CF1012C Hills 题解【DP】

    思路还是比较简单的 dp 吧,但是就是想不出来-甚至类似的方程都被自己推翻了 Description Welcome to Innopolis city. Throughout the whole y ...

  3. Atcoder arc079 D Decrease (Contestant ver.) (逆推)

    D - Decrease (Contestant ver.) Time limit : 2sec / Memory limit : 256MB Score : 600 points Problem S ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

随机推荐

  1. one-wallhaven 一个壁纸程序

    one-wallhaven 一款基于 Electron 壁纸客户端 . gitee:https://gitee.com/ml13/wallhaven-electron github:https://g ...

  2. python菜鸟教程学习4:基本数据类型

    变量:python中的变量不需要声明,但在使用前都必须要赋值,变量赋值之后才会被创建 在python中变量是没有类型的,所有的数据类型是对内存中对象的类型. 赋值:使用等号=来给变量赋值 python ...

  3. 如何剔掉 sql 语句中的尾巴,我用 C# 苦思了五种办法

    一:背景 1. 讲故事 这几天都在修复bug真的太忙了,期间也遇到了一个挺有趣bug,和大家分享一下,这是一块sql挺复杂的报表相关业务,不知道哪一位大佬在错综复杂的 嵌套 + 平行 if判断中sql ...

  4. [C/C++] 结构体内存对齐:alignas alignof pack

    简述: alignas(x):指定结构体内某个成员的对齐字节数,指定的对齐字节数不能小于它原本的字节数,且为2^n; #pragma pack(x):指定结构体的对齐方式,只能缩小结构体的对齐数,且为 ...

  5. jwt鉴权学习 (php示例代码)

    前段时间听朋友讲起 jwt鉴权,博主我是一脸懵逼,通过朋友坚持不懈的讲解,我终于听懂了,jwt就是登陆token校验嘛 然而事情并不是博主想象的那么简单,在一个艳阳高照,晴空万里的夜晚,博主手贱百度了 ...

  6. 思维导图软件iMindMap:生活工作的好帮手

    思维导图iMindMap这样的好帮手在生活工作中能帮你打破困境,,至于它有哪些力所能及的事情就是下面小编要跟你讲的: 你是否经常遇到过这样的情况: 作为学生,你觉得学习紧张,虽然三更眠五更起,还是成绩 ...

  7. 【PUPPETEER】初探之元素获取(二)

    一.涉及的知识点 如何使用css selector 常用元素获取 $ 元素选择 type (api 输入) click (api 点击) 二.学习网址 https://github.com/Googl ...

  8. LeetCode双周赛#33 题解

    5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...

  9. C语言讲义——预处理

    C预处理器是一个文本替换工具,在实际编译之前完成一些预先的处理. C预处理器(C Preprocessor)简写为 CPP 预处理器命令都是以#开头,如: #include <stdio.h&g ...

  10. 在HTML中调用打开摄像头

    1 <img src="imgs/qr.png" alt=""> 2 <video src=""></vide ...