CF627E Orchestra [矩阵计数]
\(\mathcal{Description}\)
题目大意 有一个\(r * c\)的矩阵上有\(n\)个点,问有多少个子矩阵里包含至少\(k\)个点
输入格式 第一行四个数\(r,c,n,k\),接下来\(n\)行,每行两个数\(x_i,y_i\),表示第\(i\)个点的坐标
输出格式 一行一个数表示合法子矩阵个数
数据范围 \(1\leq r,c,n\leq 3000 , 1\leq k\leq \min(n,10)\)
\(\mathcal{Solution}\)
这题好难
题目要求至少包含了\(k\)个点的子矩阵,\(k\)很小
朴素的想法是枚举上边界,下边界,然后在中间尺取,这样是\(O\left(n^3\right)\)的
反过来考虑,从下往上枚举每一行
先算出以这一行的每个顶点为左上角,最下面一行为第\(c\)的所有合法矩阵个数
计算方法考虑尺取即可
再考虑最下面一行逐渐往上走的合法矩阵个数
这个过程中,点是在不断变少的
考虑算出将最下面一行变为其上面那一行时合法矩阵的减少量,再用原来的合法矩阵量减去,得到最下面一行往上移一行后的合法矩阵数量
如何计算合法矩阵的减少量
枚举这一行中的每个点,计算出包含这个点且点数刚好为\(k\)的矩阵个数,然后删去这个点
计算方法也是尺取,另外,尺取时用一个链表表示该行中下一个点和上一个点的位置,这样尺取复杂度就是该行点数,而不是\(m\)
这样就能算出删去这一行中所有点后不合法的矩阵个数
那么往上移一行合法矩阵就会减去这些矩阵
如此计算,总复杂度为
\(O\left(n^2k+npk\right)\)
如有不懂之处,请参考代码
如仍有不懂之处可在评论提出,博主看到会给予回复
\(\mathcal{Code}\)
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年10月15日 星期二 15时37分21秒
*******************************/
#include <cstdio>
#include <fstream>
#include <vector>
#define ll long long
using namespace std;
const int maxn = 3005;
int n,m,p,k;
int s[maxn],t[maxn],last[maxn],nxt[maxn];
ll ans;
vector <int> dot[maxn];
int main()
{
scanf("%d%d%d%d",&n,&m,&p,&k);//求n行m列p个点至少包含k个点的矩阵个数
for (int i=1;i<=p;++i){
int x,y;
scanf("%d%d",&x,&y);
dot[x].push_back(y);//每行的点
}
for (int u=n;u>=1;--u){
for (int i=0;i<dot[u].size();++i) ++s[dot[u][i]];//s[i] -> 第n行到第u行上第i列的点数
int l=1,r=0,num=0;
ll inc=0;
while (true){
while (r+1<=m&&num<k) num+=s[++r];
if (num<k) break;
while (l<=r&&num>=k) num-=s[l++],inc+=m-r+1;//inc 合法矩阵个数
}
for (int i=1;i<=m;++i) t[i]=s[i];
for (int i=0;i<=m+1;++i) last[i]=i-1,nxt[i]=i+1;
for (int i=1;i<=m;++i)
if (!s[i]) last[nxt[i]]=last[i],nxt[last[i]]=nxt[i];
for (int d=n;d>=u;--d){
ans+=inc;
for (int i=0;i<dot[d].size();++i){
int cur=dot[d][i],sl=t[cur],sr=0;
l=r=cur;
while (nxt[r]<=m&&sl+sr+t[nxt[r]]<=k) sr+=t[r=nxt[r]];
while (true){
if (sl+sr==k) inc-=(l-last[l])*(nxt[r]-r);
sl+=t[l=last[l]];
if (!l||sl>k) break;
while (sl+sr>k) sr-=t[r],r=last[r];
}
--t[cur];
if (!t[cur]) last[nxt[cur]]=last[cur],nxt[last[cur]]=nxt[cur];
}
}
}
printf("%lld\n",ans);
return 0;
}
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧
CF627E Orchestra [矩阵计数]的更多相关文章
- All-one Matrices
All-one Matrices 单调栈 最大全一矩阵计数 #include<bits/stdc++.h> #define maxn 3005 using namespace std; # ...
- 斯坦福NLP课程 | 第2讲 - 词向量进阶
作者:韩信子@ShowMeAI,路遥@ShowMeAI,奇异果@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/36 本文地址:http://www. ...
- [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)
In some countries building highways takes a lot of time... Maybe that's because there are many possi ...
- [Sdoi2017]序列计数 [矩阵快速幂]
[Sdoi2017]序列计数 题意:长为\(n \le 10^9\)由不超过\(m \le 2 \cdot 10^7\)的正整数构成的和为\(t\le 100\)的倍数且至少有一个质数的序列个数 总- ...
- hdu 2865 Polya计数+(矩阵 or 找规律 求C)
Birthday Toy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法
BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ...
- 生成树的计数 Matrix-Tree(矩阵树)定理
信息学竞赛中,有关生成树的最优化问题如最小生成树等是我们经常遇到的,而对生成树的计数及其相关问题则少有涉及.事实上,生成树的计数是十分有意义的,在许多方面都有着广泛的应用.本文从一道信息学竞赛中出现的 ...
- [SDOI2009]HH去散步 「矩阵乘法计数」
计数问题也许可以转化为矩阵乘法形式 比如若该题没有不能在一条边上重复走的条件限制,那么直接将邻接矩阵转化为矩阵乘法即可 故 矩阵乘法计数 对于计数问题,若可以将 \(n\) 个点表示成 \(n \ti ...
- 【BZOJ 4818】 4818: [Sdoi2017]序列计数 (矩阵乘法、容斥计数)
4818: [Sdoi2017]序列计数 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 560 Solved: 359 Description Al ...
随机推荐
- CMD下文件操作
CMD下常用文件操作指令 1.输入盘符 如C: 然后回车,相当于进了C盘(c盘一般进的是桌面目录) 2.输入 cd 目录名 然后回车(目录名是c盘中的一级目录名,也可为c盘中的目录路径).如cd mm ...
- 微信小程序前端promise封装
config.js const config = { base_url_api : "https://douban.uieee.com/v2/movie/", } export { ...
- 关于移动虚拟机后,linux网卡启动异常问题解决
废话不多说,直接上解决办法. 首先执行命令:ifconfig -a 会发现原来是eth0, 而现在变成了eth1了 然后我们编辑规则配置信息: vim /etc/udev/rule.d/70-pers ...
- MySQL explain使用
1.介绍 EXPLAIN 命令用于SQL语句的查询执行计划.这条命令的输出结果能够让我们了解MySQL 优化器(optimlzer)是如何执行SQL 语句的.这条命令并没有提供任何调整建议,但它能够提 ...
- restframework之节流
基本思路(原生Django而言): 在django2.x中,若出现节流(访问频率控制)的需求,我们首先想到的是使用一个字典(dict类型)来存储所有IP地址的访问时间记录,这是针对于匿名用户(IP)而 ...
- 手把手实例对比String、StringBuilder字符串的连接效率及StringBuilder和StringBuffer线程安全的比较
一.字符串连接的效率问题 使用String连接字符串时为什么慢? 小知识点 java中对数组进行初始化后,该数组所占的内存空间.数组长度都是不可变的. 创建一个字符串,为字符串对象分配内存空间,会耗费 ...
- 分布式并行计算MapReduce
作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3319 1.用自己的话阐明Hadoop平台上HDFS和MapReduce ...
- 善用mysql中的FROM_UNIXTIME()函数和UNIX_TIMESTAMP()函数
我们经常会面临要从数据库里判断时间,取出特定日期的查询.但是数据库里储存的都是unix时间戳,处理起来并不是特别友好.幸而MYSQL提供了几个处理时间戳的函数,可以帮助我们在查询的时候,就将时间戳格式 ...
- 003-maven开发Java脚手架archrtype-技术点说明
一.概述 二.技术点说明 2.1.项目结构 凡auto包或文件件,均会被代码生成器再次生成二修改 1.model层 po:BasePO基础类,统一了数据库的基础字段[数据库必须添加如下,与mybati ...
- python初级(302) 1 环境搭建及简单使用
一.安装anaconda(python环境) 1 地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=A 选择Ana ...